diff --git a/previews/PR347/.documenter-siteinfo.json b/previews/PR347/.documenter-siteinfo.json new file mode 100644 index 000000000..cfac9c8cf --- /dev/null +++ b/previews/PR347/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.10.3","generation_timestamp":"2024-05-07T12:36:41","documenter_version":"1.4.1"}} \ No newline at end of file diff --git a/previews/PR347/assets/citations.css b/previews/PR347/assets/citations.css new file mode 100644 index 000000000..76140e873 --- /dev/null +++ b/previews/PR347/assets/citations.css @@ -0,0 +1,17 @@ +.citation dl { + display: grid; + grid-template-columns: max-content auto; } +.citation dt { + grid-column-start: 1; } +.citation dd { + grid-column-start: 2; + margin-bottom: 0.75em; } +.citation ul { + padding: 0 0 2.25em 0; + margin: 0; + list-style: none;} +.citation ul li { + text-indent: -2.25em; + margin: 0.33em 0.5em 0.5em 2.25em;} +.citation ol li { + padding-left:0.75em;} diff --git a/previews/PR347/assets/documenter.js b/previews/PR347/assets/documenter.js new file mode 100644 index 000000000..c6562b558 --- /dev/null +++ b/previews/PR347/assets/documenter.js @@ -0,0 +1,1050 @@ +// Generated by Documenter.jl +requirejs.config({ + paths: { + 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min', + 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', + 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min', + 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min', + 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', + 'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min', + 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min', + 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia-repl.min', + }, + shim: { + "highlight-julia": { + "deps": [ + "highlight" + ] + }, + "katex-auto-render": { + "deps": [ + "katex" + ] + }, + "headroom-jquery": { + "deps": [ + "jquery", + "headroom" + ] + }, + "highlight-julia-repl": { + "deps": [ + "highlight" + ] + } +} +}); +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) { +$(document).ready(function() { + renderMathInElement( + document.body, + { + "delimiters": [ + { + "left": "$", + "right": "$", + "display": false + }, + { + "left": "$$", + "right": "$$", + "display": true + }, + { + "left": "\\[", + "right": "\\]", + "display": true + } + ] +} + + ); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($) { +$(document).ready(function() { + hljs.highlightAll(); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +let timer = 0; +var isExpanded = true; + +$(document).on("click", ".docstring header", function () { + let articleToggleTitle = "Expand docstring"; + + debounce(() => { + 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 (event) { + let articleToggleTitle = "Expand docstring"; + let navArticleToggleTitle = "Expand all docstrings"; + let animationSpeed = event.noToggleAnimation ? 0 : 400; + + 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(animationSpeed); + } 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(animationSpeed); + } + + $(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'], function($) { + +$(document).ready(function () { + let meta = $("div[data-docstringscollapsed]").data(); + + if (meta?.docstringscollapsed) { + $("#documenter-article-toggle-button").trigger({ + type: "click", + noToggleAnimation: true, + }); + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +/* +To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +PSEUDOCODE: + +Searching happens automatically as the user types or adjusts the selected filters. +To preserve responsiveness, as much as possible of the slow parts of the search are done +in a web worker. Searching and result generation are done in the worker, and filtering and +DOM updates are done in the main thread. The filters are in the main thread as they should +be very quick to apply. This lets filters be changed without re-searching with minisearch +(which is possible even if filtering is on the worker thread) and also lets filters be +changed _while_ the worker is searching and without message passing (neither of which are +possible if filtering is on the worker thread) + +SEARCH WORKER: + +Import minisearch + +Build index + +On message from main thread + run search + find the first 200 unique results from each category, and compute their divs for display + note that this is necessary and sufficient information for the main thread to find the + first 200 unique results from any given filter set + post results to main thread + +MAIN: + +Launch worker + +Declare nonconstant globals (worker_is_running, last_search_text, unfiltered_results) + +On text update + if worker is not running, launch_search() + +launch_search + set worker_is_running to true, set last_search_text to the search text + post the search query to worker + +on message from worker + if last_search_text is not the same as the text in the search field, + the latest search result is not reflective of the latest search query, so update again + launch_search() + otherwise + set worker_is_running to false + + regardless, display the new search results to the user + save the unfiltered_results as a global + update_search() + +on filter click + adjust the filter selection + update_search() + +update_search + apply search filters by looping through the unfiltered_results and finding the first 200 + unique results that match the filters + + Update the DOM +*/ + +/////// SEARCH WORKER /////// + +function worker_function(documenterSearchIndex, documenterBaseURL, filters) { + importScripts( + "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js" + ); + + let data = documenterSearchIndex.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 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@!]+$/, ""); + + word = word.toLowerCase(); + } + + 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: { + prefix: true, + boost: { title: 100 }, + fuzzy: 2, + }, + }); + + index.addAll(data); + + /** + * Used to map characters to HTML entities. + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + const htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + }; + + /** + * Used to match HTML entities and HTML characters. + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + const reUnescapedHtml = /[&<>"']/g; + const reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** + * Escape function from lodash + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + function escape(string) { + return string && reHasUnescapedHtml.test(string) + ? string.replace(reUnescapedHtml, (chr) => htmlEscapes[chr]) + : string || ""; + } + + /** + * 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(`${querystring}`, "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 + + text = text.length ? escape(text) : ""; + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`${escape(querystring)}`, "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 = ` + +
+
${escape(result.title)}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; + } + + self.onmessage = function (e) { + let query = e.data; + let results = index.search(query, { + filter: (result) => { + // Only return relevant results + return result.score >= 1; + }, + }); + + // Pre-filter to deduplicate and limit to 200 per category to the extent + // possible without knowing what the filters are. + let filtered_results = []; + let counts = {}; + for (let filter of filters) { + counts[filter] = 0; + } + let present = {}; + + for (let result of results) { + cat = result.category; + cnt = counts[cat]; + if (cnt < 200) { + id = cat + "---" + result.location; + if (present[id]) { + continue; + } + present[id] = true; + filtered_results.push({ + location: result.location, + category: cat, + div: make_search_result(result, query), + }); + } + } + + postMessage(filtered_results); + }; +} + +// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript! +const filters = [ + ...new Set(documenterSearchIndex["docs"].map((x) => x.category)), +]; +const worker_str = + "(" + + worker_function.toString() + + ")(" + + JSON.stringify(documenterSearchIndex["docs"]) + + "," + + JSON.stringify(documenterBaseURL) + + "," + + JSON.stringify(filters) + + ")"; +const worker_blob = new Blob([worker_str], { type: "text/javascript" }); +const worker = new Worker(URL.createObjectURL(worker_blob)); + +/////// SEARCH MAIN /////// + +// Whether the worker is currently handling a search. This is a boolean +// as the worker only ever handles 1 or 0 searches at a time. +var worker_is_running = false; + +// The last search text that was sent to the worker. This is used to determine +// if the worker should be launched again when it reports back results. +var last_search_text = ""; + +// The results of the last search. This, in combination with the state of the filters +// in the DOM, is used compute the results to display on calls to update_search. +var unfiltered_results = []; + +// Which filter is currently selected +var selected_filter = ""; + +$(document).on("input", ".documenter-search-input", function (event) { + if (!worker_is_running) { + launch_search(); + } +}); + +function launch_search() { + worker_is_running = true; + last_search_text = $(".documenter-search-input").val(); + worker.postMessage(last_search_text); +} + +worker.onmessage = function (e) { + if (last_search_text !== $(".documenter-search-input").val()) { + launch_search(); + } else { + worker_is_running = false; + } + + unfiltered_results = e.data; + update_search(); +}; + +$(document).on("click", ".search-filter", function () { + if ($(this).hasClass("search-filter-selected")) { + selected_filter = ""; + } else { + selected_filter = $(this).text().toLowerCase(); + } + + // This updates search results and toggles classes for UI: + update_search(); +}); + +/** + * Make/Update the search component + */ +function update_search() { + let querystring = $(".documenter-search-input").val(); + + if (querystring.trim()) { + if (selected_filter == "") { + results = unfiltered_results; + } else { + results = unfiltered_results.filter((result) => { + return selected_filter == result.category.toLowerCase(); + }); + } + + let search_result_container = ``; + let modal_filters = make_modal_body_filters(); + let search_divider = `
`; + + if (results.length) { + let links = []; + let count = 0; + let search_results = ""; + + for (var i = 0, n = results.length; i < n && count < 200; ++i) { + let result = results[i]; + if (result.location && !links.includes(result.location)) { + search_results += result.div; + count++; + links.push(result.location); + } + } + + if (count == 1) { + count_str = "1 result"; + } else if (count == 200) { + count_str = "200+ results"; + } else { + count_str = count + " results"; + } + let result_count = `
${count_str}
`; + + 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 { + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(` +
Type something to get started!
+ `); + } +} + +/** + * Make the modal filter html + * + * @returns string + */ +function make_modal_body_filters() { + let str = filters + .map((val) => { + if (selected_filter == val.toLowerCase()) { + return `${val}`; + } else { + return `${val}`; + } + }) + .join(""); + + return ` +
+ Filters: + ${str} +
`; +} + +}) +//////////////////////////////////////////////////////////////////////////////// +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($) { + +$(document).ready(function () { + let search_modal_header = ` + + `; + + let initial_search_body = ` +
Type something to get started!
+ `; + + let search_modal_footer = ` + + `; + + $(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/PR347/assets/themes/documenter-dark.css b/previews/PR347/assets/themes/documenter-dark.css new file mode 100644 index 000000000..1d7170158 --- /dev/null +++ b/previews/PR347/assets/themes/documenter-dark.css @@ -0,0 +1,7 @@ +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 .file-cta,html.theme--documenter-dark .file-name,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,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 a:hover code{color:#1dd2af}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 .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/PR347/assets/themes/documenter-light.css b/previews/PR347/assets/themes/documenter-light.css new file mode 100644 index 000000000..07f9d0883 --- /dev/null +++ b/previews/PR347/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 a:hover code{color:#363636}.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/PR347/assets/themeswap.js b/previews/PR347/assets/themeswap.js new file mode 100644 index 000000000..9f5eebe6a --- /dev/null +++ b/previews/PR347/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/PR347/assets/warner.js b/previews/PR347/assets/warner.js new file mode 100644 index 000000000..3f6f5d008 --- /dev/null +++ b/previews/PR347/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/PR347/bibliography/index.html b/previews/PR347/bibliography/index.html new file mode 100644 index 000000000..30ea189fc --- /dev/null +++ b/previews/PR347/bibliography/index.html @@ -0,0 +1,2 @@ + +Bibliography · SumOfSquares

Bibliography

diff --git a/previews/PR347/constraints/index.html b/previews/PR347/constraints/index.html new file mode 100644 index 000000000..a76275321 --- /dev/null +++ b/previews/PR347/constraints/index.html @@ -0,0 +1,161 @@ + +Constraints · SumOfSquares

Constraints

Equality constraints between polynomials

Equality between polynomials in PolyJuMP uses the same syntax as equality between affine or quadratic expression in JuMP. For instance, creating two quadratic n-variate polynomials p and q that must sum up to one can be done as follows:

julia> n = 3
+3
+
+julia> using DynamicPolynomials
+
+julia> @polyvar x[1:n]
+(Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}[x₁, x₂, x₃],)
+
+julia> X = monomials(x, 0:2)
+10-element MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}:
+ 1
+ x₃
+ x₂
+ x₁
+ x₃²
+ x₂x₃
+ x₂²
+ x₁x₃
+ x₁x₂
+ x₁²
+
+julia> using SumOfSquares
+
+julia> model = Model()
+A JuMP Model
+Feasibility problem with:
+Variables: 0
+Model mode: AUTOMATIC
+CachingOptimizer state: NO_OPTIMIZER
+Solver name: No optimizer attached.
+
+julia> @variable(model, p, Poly(X))
+(_[1]) + (_[2])x₃ + (_[3])x₂ + (_[4])x₁ + (_[5])x₃² + (_[6])x₂x₃ + (_[7])x₂² + (_[8])x₁x₃ + (_[9])x₁x₂ + (_[10])x₁²
+
+julia> @variable(model, q, Poly(X))
+(_[11]) + (_[12])x₃ + (_[13])x₂ + (_[14])x₁ + (_[15])x₃² + (_[16])x₂x₃ + (_[17])x₂² + (_[18])x₁x₃ + (_[19])x₁x₂ + (_[20])x₁²
+
+julia> @constraint(model, p + q == 1)
+(_[1] + _[11] - 1) + (_[2] + _[12])x₃ + (_[3] + _[13])x₂ + (_[4] + _[14])x₁ + (_[5] + _[15])x₃² + (_[6] + _[16])x₂x₃ + (_[7] + _[17])x₂² + (_[8] + _[18])x₁x₃ + (_[9] + _[19])x₁x₂ + (_[10] + _[20])x₁² ∈ PolyJuMP.ZeroPoly()

Vectorized constraints can also be used as well as vector of constraints, named constraints, ... For instance, if P and Q are two $n \times n$ matrices of polynomials, the following constraints the sum of rows and columns to match:

@constraint(model, con[i=1:n], sum(P[i, :]) == sum(Q[:, i]))

and con[i] contains the reference to the constraint between the ith row of P and the ith column of Q.

Inequality constraints between polynomials

Polynomials can be constrained to be sum-of-squares with the in syntax. For instance, to constrain a polynomial p to be sum-of-squares, do

julia> @constraint(model, p in SOSCone())
+(_[1]) + (_[2])x₃ + (_[3])x₂ + (_[4])x₁ + (_[5])x₃² + (_[6])x₂x₃ + (_[7])x₂² + (_[8])x₁x₃ + (_[9])x₁x₂ + (_[10])x₁² is SOS

Automatically interpreting polynomial nonnegativity as a sum-of-squares constraint

As detailed in When is nonnegativity equivalent to sum of squares ?, the nonnegativity of a polynomial is not equivalent to the existence of a sum-of-squares decomposition. However, if explicitely specified, nonnegativity constraints can be automatically interpreted as sum-of-squares constraints. The simplest way to do that is to create the model with

model = SOSModel(...)

instead of

model = Model(...)

An alternative equivalent way is to call setpolymodule! after creating the model:

julia> setpolymodule!(model, SumOfSquares)

This second approach may be useful if the SumOfSquares JuMP extension need to be used with another JuMP extension that also has a special model constructor. A third alternative is the following:

julia> PolyJuMP.setdefault!(model, PolyJuMP.NonNegPoly, SOSCone)
+SOSCone (alias for NonnegPolyInnerCone{MathOptInterface.PositiveSemidefiniteConeTriangle})
+
+julia> PolyJuMP.setdefault!(model, PolyJuMP.PosDefPolyMatrix, SOSMatrixCone)
+SOSMatrixCone (alias for PSDMatrixInnerCone{MathOptInterface.PositiveSemidefiniteConeTriangle})

This approach adds the flexibility to choose the default cone for

  • constraints of the form @constraint(mode, ..., some_polynomial ≥ other_polynomial, ...) which is the cone given as default to PolyJuMP.NonNegPoly; and
  • constraints of the form @constraint(mode, ..., some_matrix_of_polynomial in PSDCone(), ...) or @constraint(mode, ..., some_matrix_of_polynomial >= other_matrix_of_polynomial, PSDCone(), ...) which is the cone given as default to PolyJuMP.NonNegPolyMatrix.

For instance, to use the diagonally-dominant-sum-of-squares cone (see [Definition 2, AM17]) for the first type of contraints, do

julia> PolyJuMP.setdefault!(model, PolyJuMP.NonNegPoly, DSOSCone)
+DSOSCone (alias for NonnegPolyInnerCone{SumOfSquares.DiagonallyDominantConeTriangle})

Changing the polynomial basis

As introduced in Choosing a polynomial basis, there may be numerical advantages to use another basis than the standard monomial basis when creating polynomial variables. Similarly, other polynomial bases can be used for polynomial constraints. However, for constraints, the polynomial space is determined by the polynomial constrained to be nonnegative. For instance, consider the constraint:

julia> using DynamicPolynomials
+
+julia> @polyvar x y
+(x, y)
+
+julia> using SumOfSquares
+
+julia> model = SOSModel()
+A JuMP Model
+Feasibility problem with:
+Variables: 0
+Model mode: AUTOMATIC
+CachingOptimizer state: NO_OPTIMIZER
+Solver name: No optimizer attached.
+
+julia> @variable(model, α)
+α
+
+julia> @variable(model, β)
+β
+
+julia> @constraint(model, α * x^2 + β * y^2 ≥ (α - β) * x * y)
+(β)y² + (-α + β)xy + (α)x² is SOS

where α and β are JuMP decision variables and x and y are polynomial variables. Since the polynomial is a quadratic form, the sum-of-squares certificate is also a quadratic form (see [Section~3.3.4, BPT12]). Hence the default polynomial basis used for the [Nonnegative polynomial variables] certificate is MonomialBasis([x, y]), that is, we search for a positive semidefinite matrix Q such that

\[\alpha x^2 + \beta y^2 - (\alpha - \beta) x y = X^\top Q X\]

where $X = (x, y)$.

As the polynomial space is determined by the polynomial being constrained, only the basis type needs to be given. For instance, to use the scaled monomial basis in the example above, use

julia> @constraint(model, α * x^2 + β * y^2 ≥ (α - β) * x * y, basis = ScaledMonomialBasis)
+(β)y² + (-α + β)xy + (α)x² is SOS

Polynomial nonnegativity on a subset of the space

By default, the constraint

julia> @constraint(model, x^3 - x^2 + 2x*y -y^2 + y^3 >= α)
+(-α) + (-1)y² + (2)xy + (-1)x² + (1)y³ + (1)x³ is SOS

constrains the polynomial to be nonnegative for every real numbers x and y. However, the set of points (x, y) for which the polynomial is constrained to be nonnegative can be specified by the domain keyword:

julia> S = @set x >= 0 && y >= 0 && x + y >= 1;
+
+julia> @constraint(model, x^3 - x^2 + 2x*y -y^2 + y^3 >= α, domain = S)
+(-α) + (-1)y² + (2)xy + (-1)x² + (1)y³ + (1)x³ is SOS

See this notebook for a detailed example.

Dual of polynomial constraints

The dual of a polynomial constraint cref is a moment serie μ as defined in MultivariateMoments. The dual can be obtained with the dual function as with classical dual values in JuMP.

μ = dual(cref)

By dual of a Sum-of-Squares constraint, we may mean different things and the meaning chosen for dual function was chosen for consistency with the definition of the JuMP dual function to ensure that generic code will work as expected with Sum-of-Squares constraints. In a Sum-of-Squares constraint, a polynomial $p$ is constraint to be SOS in some domain defined by polynomial q_i. So p(x) is constrained to be equal to s(x) = s_0(x) + s_1(x) * q_1(x) + s_2(x) * q_2(x) + ... where the s_i(x) polynomials are Sum-of-Squares. The dual of the equality constraint between p(x) and s(x) is given by SumOfSquares.MultivariateMoments.moments.

μ = moments(cref)

Note that the dual and moments may give different results. For instance, the output of dual only contains the moments corresponding to monomials of p while the output of moments may give the moments of other monomials if s(x) has more monomials than p(x). Besides, if the domain contains polynomial, equalities, only the remainder of p(x) - s(x) modulo the ideal is constrained to be zero, see Corollary 2 of [CLO13]. In that case, the output moments is the dual of the constraint on the remainder so some monomials may have different moments with dual or moments.

The dual of the Sum-of-Squares constraint on s_0(x), commonly referred to as the the matrix of moments can be obtained using moment_matrix:

ν = moment_matrix(cref)

The atomic_measure function of MultivariateMoments can be used to check if there exists an atomic measure (i.e. a measure that is a sum of Dirac measures) that has the moments given in the the moment matrix ν. This can be used for instance in polynomial optimization (see this notebook) or stability analysis (see this notebook).

References

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

[CLO13] Cox, D., Little, J., & OShea, D. Ideals, varieties, and algorithms: an introduction to computational algebraic geometry and commutative algebra. Springer Science & Business Media, 2013.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization. ArXiv e-prints, 2017.

API Reference

Default choice for the maxdegree keyword:

SumOfSquares.default_maxdegreeFunction
default_maxdegree(monos, domain)

Return the default maxdegree to use for certifying a polynomial with monomials monos to be Sum-of-Squares over the domain domain. By default, the maximum of the maxdegree of monos and of all multipliers of the domain are used so that at least constant multipliers can be used with a Putinar certificate.

source

Special case that is second-order cone representable:

Inner approximations of the PSD cone that do not require semidefinite programming:

SumOfSquares.DiagonallyDominantConeTriangleType
struct DiagonallyDominantConeTriangle <: MOI.AbstractSymmetricMatrixSetTriangle
+    side_dimension::Int
+end

See Definition 4 of [AM17] for a precise definition of the last two items.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.

source
SumOfSquares.ScaledDiagonallyDominantConeTriangleType
struct ScaledDiagonallyDominantConeTriangle <: MOI.AbstractSymmetricMatrixSetTriangle
+    side_dimension::Int
+end

See Definition 4 of [AM17] for a precise definition of the last two items.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.

source

Approximations of the cone of nonnegative polynomials:

SumOfSquares.NonnegPolyInnerConeType
struct NonnegPolyInnerCone{MCT <: MOI.AbstractVectorSet}
+end

Inner approximation of the cone of nonnegative polynomials defined by the set of polynomials of the form

X^\top Q X

where X is a vector of monomials and Q is a symmetric matrix that belongs to the cone psd_inner.

source
SumOfSquares.SDSOSConeType
const SDSOSCone = NonnegPolyInnerCone{ScaledDiagonallyDominantConeTriangle}

Scaled-diagonally-dominant-sum-of-squares cone; see [Definition 2, AM17] and NonnegPolyInnerCone.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.

source
SumOfSquares.DSOSConeType
const DSOSCone = NonnegPolyInnerCone{DiagonallyDominantConeTriangle}

Diagonally-dominant-sum-of-squares cone; see [Definition 2, AM17] and NonnegPolyInnerCone.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.

source

Approximations of the cone of positive semidefinite polynomial matrices:

SumOfSquares.PSDMatrixInnerConeType
struct PSDMatrixInnerCone{MCT <: MOI.AbstractVectorSet} <: PolyJuMP.PolynomialSet
+end

Inner approximation of the cone of polynomial matrices P(x) that are positive semidefinite for any x defined by the set of $n \times n$ polynomial matrices such that the polynomial $y^\top P(x) y$ belongs to NonnegPolyInnerCone{MCT} where y is a vector of $n$ auxiliary polynomial variables.

source
SumOfSquares.SOSMatrixConeType
const SOSMatrixCone = PSDMatrixInnerCone{MOI.PositiveSemidefiniteConeTriangle}

Sum-of-squares matrices cone; see [Section 3.3.2, BPT12] and PSDMatrixInnerCone.

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

source

Approximations of the cone of convex polynomials:

SumOfSquares.ConvexPolyInnerConeType
struct ConvexPolyInnerCone{MCT} <: PolyJuMP.PolynomialSet end

Inner approximation of the set of convex polynomials defined by the set of polynomials such that their hessian belongs to to the set PSDMatrixInnerCone{MCT}()

source
SumOfSquares.SOSConvexConeType
const SOSConvexCone = ConvexPolyInnerCone{MOI.PositiveSemidefiniteConeTriangle}

Sum-of-squares convex polynomials cone; see [Section 3.3.3, BPT12] and ConvexPolyInnerCone.

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

source

Approximations of the cone of copositive matrices:

SumOfSquares.CopositiveInnerType
struct CopositiveInner{S} <: PolyJuMP.PolynomialSet
+    # Inner approximation of the PSD cone, i.e. typically either
+    # `SOSCone`, `DSOSCone` or `SDSOSCone`,
+    psd_inner::S
+end

A symmetric matrix $Q$ is copositive if $x^{\top} Q x \ge 0$ for all vector $x$ in the nonnegative orthant. Checking copositivity is a co-NP-complete problem [MK87] and this cone is only the inner approximation of the cone of copositive symmetric matrices given by Minknowski sum of psd_inner and the cone of symmetric matrices with nonnegative entries (the diagonal entries can be chosen to be zero) [Lemma 3.164, BPT12].

The matrix with nonnegative entries can be interpreted as lagrangian multipliers. For instance,

@polyvar x y
+@constraint(model, x^2 - 2x*y + y^2 in CopositiveInner(SOSCone()))

is equivalent to

# Matrix that we require to be copositive
+Q = [ 1 -1
+     -1  1]
+λ = @variable(model, lower_bound=0)
+# Symmetric matrix of nonnegative entries
+Λ = [0 λ
+     λ 0]
+using LinearAlgebra # For `Symmetric`
+@constraint(model, Symmetric(Q - Λ) in PSDCone())

which is equivalent to

@polyvar x y
+λ = @variable(model, lower_bound=0)
+@constraint(model, x^2 - 2x*y + y^2 - 2*λ * x*y in SOSCone())

which is the same as, using the domain keyword,

@polyvar x y
+@constraint(model, x^2 - 2x*y + y^2 in SOSCone(), domain = @set x*y ≥ 0)

As an important difference with its equivalent forms, the GramMatrixAttribute for the copositive constraint is given by matrix Q while for the equivalent form using the domainkeyword, the value of the attribute would correspond to the the gram matrix in thepsd_innercone, i.e. which should be equal toQ - Λ`.

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

[MK87] K. G. Murty and S. N. Kabadi. Some NP-complete problems in quadratic and nonlinear programming. Mathematical programming, 39:117–129, 1987.

source

Types of sparsity

SumOfSquares.Certificate.Sparsity.VariableType
struct Sparsity.Variable <: Sparsity.Pattern end

Variable or correlative sparsity as developed in [WSMM06].

[WSMM06] Waki, Hayato, Sunyoung Kim, Masakazu Kojima, and Masakazu Muramatsu. "Sums of squares and semidefinite program relaxations for polynomial optimization problems with structured sparsity." SIAM Journal on Optimization 17, no. 1 (2006): 218-242.

source
SumOfSquares.Certificate.Sparsity.MonomialType
struct Sparsity.Monomial{C<:CEG.AbstractCompletion} <: Sparsity.Pattern
+    completion::C
+    k::Int
+    use_all_monomials::Bool
+end

Monomial or term sparsity as developed in [WML20a, WML20b]. The completion field should be ClusterCompletion() [default] for the block-closure or cluster completion [WML20a], and ChordalCompletion() for chordal completion [WML20b]. The integer k [default=0] corresponds to Σ_k defined in [(3.2), WML20a] and k = 0 corresponds to Σ_* defined in [(3.3), WML20a]. If use_all_monomials is false then some monomials of the basis might be dropped from the basis if not needed.

[WML20a] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. TSSOS: A Moment-SOS hierarchy that exploits term sparsity. arXiv preprint arXiv:1912.08899 (2020).

[WML20b] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension. arXiv preprint arXiv:2003.03210 (2020).

source
SumOfSquares.Certificate.Sparsity.SignSymmetryType
struct SignSymmetry <: Sparsity.Pattern end

Sign symmetry as developed in [Section III.C, L09]. Let n be the number of variables. A sign-symmetry is a binary vector r of {0, 1}^n such that dot(r, e) is even for all exponent e.

Let o(e) be the binary vector of {0, 1}^n for which the ith bit is i iff the ith entry of e is odd. Let O be the set of o(e) for exponents of e. A binary vector r is a sign-symmetry if an only if it is orthogonal to all the elements of O.

Since we are only interested in the orthogonal subspace, say R, of O, even if O is not a linear subspace (i.e., it is not invariant under xor), we compute its span. We start by creating row echelon form of the span of O using XORSpace. We then compute a basis for R. The set R of sign symmetries will be the span of this basis.

Let a, b be exponents of monomials of the gram basis. For any r in R,

⟨r, o(a + b)⟩ = ⟨r, xor(o(a), o(b)⟩ = xor(⟨r, o(a)⟩, ⟨r, o(b)⟩)

For o(a, b) to be sign symmetric, this scalar product should be zero for all sign symmetry r. This is equivalent to saying that ⟨r, o(a)⟩ and ⟨r, o(b)⟩ are equal for all r in R. In other words, the projection of o(a) and o(b) to R have the same coordinates in the basis. If we order the monomials by grouping them by equal coordinates of projection, we see that the product that are sign symmetric form a block diagonal structure. This means that we can group the monomials by these coordinates.

[L09] Löfberg, Johan. Pre-and post-processing sum-of-squares programs in practice. IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011.

source
SumOfSquares.Certificate.Sparsity.XORSpaceType
mutable struct XORSpace{T<:Integer}
+    dimension::Int
+    basis::Vector{T}
+end

Basis for a linear subspace of the Hamming space (i.e. set of binary string {0, 1}^n of length n) represented in the bits of an integer of type T. This is used to implement Certificate.Sparsity.SignSymmetry.

Consider the scalar product ⟨a, b⟩ which returns the the xor of the bits of a & b. It is a scalar product since ⟨a, b⟩ = ⟨b, a⟩ and ⟨a, xor(b, c)⟩ = xor(⟨a, b⟩, ⟨a, c⟩).

We have two options here to compute the orthogonal space.

The first one is to build an orthogonal basis with some kind of Gram-Schmidt process and then to obtain the orthogonal space by removing the projection from each vector of the basis.

The second option, which is the one we use here is to compute the row echelon form and then read out the orthogonal subspace directly from it. For instance, if the row echelon form is

1 a 0 c e
+  b 1 d f

then the orthogonal basis is

a 1 b 0 0
+c 0 d 1 0
+e 0 f 0 1

The basis vector has dimension nonzero elements. Any element added with push! can be obtained as the xor of some of the elements of basis. Moreover, the basis is kept in row echelon form in the sense that the first, second, ..., i - 1th bits of basis[i] are zero and basis[i] is zero if its ith bit is not one.

source

Ideal certificates:

SumOfSquares.Certificate.MaxDegreeType
struct MaxDegree{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: SimpleIdealCertificate{CT, BT}
+    cone::CT
+    basis::Type{BT}
+    maxdegree::Int
+end

The MaxDegree certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by exhibiting a Sum-of-Squares polynomials σ(x) such that p(x) - σ(x) is guaranteed to be zero for all x such that h_i(x) = 0. The polynomial σ(x) is search over cone with a basis of type basis such that the degree of σ(x) does not exceed maxdegree.

source
SumOfSquares.Certificate.FixedBasisType
struct FixedBasis{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: SimpleIdealCertificate{CT, BT}
+    cone::CT
+    basis::BT
+end

The FixedBasis certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by exhibiting a Sum-of-Squares polynomials σ(x) such that p(x) - σ(x) is guaranteed to be zero for all x such that h_i(x) = 0. The polynomial σ(x) is search over cone with basis basis.

source
SumOfSquares.Certificate.NewtonType
struct Newton{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis, NPT <: Tuple} <: SimpleIdealCertificate{CT, BT}
+    cone::CT
+    basis::Type{BT}
+    variable_groups::NPT
+end

The Newton certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by exhibiting a Sum-of-Squares polynomials σ(x) such that p(x) - σ(x) is guaranteed to be zero for all x such that h_i(x) = 0. The polynomial σ(x) is search over cone with a basis of type basis chosen using the multipartite Newton polytope with parts variable_groups. If variable_groups = tuple() then it falls back to the classical Newton polytope with all variables in the same part.

source
SumOfSquares.Certificate.RemainderType
struct Remainder{GCT<:AbstractIdealCertificate} <: AbstractIdealCertificate
+    gram_certificate::GCT
+end

The Remainder certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by guaranteeing the remainder of p(x) modulo the ideal generated by ⟨h_i⟩ to be nonnegative for all x such that h_i(x) = 0 using the certificate gram_certificate. For instance, if gram_certificate is SumOfSquares.Certificate.Newton, then the certificate Remainder(gram_certificate) will take the remainder before computing the Newton polytope hence might generate a much smaller Newton polytope hence a smaller basis and smaller semidefinite program. However, this then corresponds to a lower degree of the hierarchy which might be insufficient to find a certificate.

source
SumOfSquares.Certificate.Sparsity.IdealType
struct Sparsity.Ideal{S <: Sparsity.Pattern, C <: AbstractIdealCertificate} <: SumOfSquares.Certificate.AbstractIdealCertificate
+    sparsity::S
+    certificate::C
+end

Same certificate as certificate except that the Sum-of-Squares polynomial σ is modelled as a sum of Sum-of-Squares polynomials with smaller bases using the sparsity reduction sparsity.

source
SumOfSquares.Certificate.Symmetry.IdealType
struct Symmetry.Ideal{C,GT,AT<:SymbolicWedderburn.Action} <: SumOfSquares.Certificate.AbstractIdealCertificate
+    pattern::Symmetry.Pattern{GT,AT}
+    certificate::C
+end

Same certificate as certificate except that the Sum-of-Squares polynomial σ is modelled as a sum of Sum-of-Squares polynomials with smaller bases using the Symbolic Wedderburn decomposition of the symmetry pattern specified by pattern.

source

Preorder certificates:

SumOfSquares.Certificate.PutinarType
struct Putinar{
+    MC<:AbstractIdealCertificate,
+    IC<:AbstractIdealCertificate,
+} <: AbstractPreorderCertificate
+    multipliers_certificate::MC
+    ideal_certificate::IC
+    maxdegree::Int
+end

The Putinar certificate ensures the nonnegativity of p(x) for all x such that g_i(x) >= 0 and h_i(x) = 0 by exhibiting Sum-of-Squares polynomials σ_i(x) such that p(x) - ∑ σ_i(x) g_i(x) is guaranteed to be nonnegativity for all x such that h_i(x) = 0. The polynomials σ_i(x) are search over cone with a basis of type basis such that the degree of σ_i(x) g_i(x) does not exceed maxdegree.

source
SumOfSquares.Certificate.Sparsity.PreorderType
struct Sparsity.Preorder{S <: Sparsity.Pattern, C <: SumOfSquares.Certificate.AbstractPreorderCertificate} <: SumOfSquares.Certificate.AbstractPreorderCertificate
+    sparsity::S
+    certificate::C
+end

Same certificate as C except that the Sum-of-Squares polynomials σ_i are modelled as a sum of Sum-of-Squares polynomials with smaller basis using the sparsity reduction sparsity.

source

Attributes

PolyJuMP.MomentsAttributeType
MomentsAttribute(N)
+MomentsAttribute()

A constraint attribute for the vector of moments corresponding to the constraint that a polynomial is zero in the full space in result N. If the polynomial is constrained to be zero in an algebraic set, it is the moments for the constraint once it is rewritten into an constraint on the full space. If N is omitted, it is 1 by default.

Examples

Consider the following program:

@variable(model, α)
+@variable(model, β ≤ 1)
+
+using DynamicPolynomials
+@polyvar x y
+cref = @constraint(model, α * x - β * y == 0, domain = @set x == y)

The constraint is equivalent to

@constraint(model, (α - β) * y == 0)

for which the dual is the 1-element vector with the moment of y of value -1. This is the result of moments(cref). However, the dual of cref obtained by dual(cref) is the 2-elements vector with both the moments of x and y of value -1.

source
SumOfSquares.GramMatrixType
struct GramMatrix{T, B, U, MT <: AbstractMatrix{T}} <: AbstractGramMatrix{T, B, U}
+    Q::MT
+    basis::B
+end

Gram matrix $x^\top Q x$ where Q is a symmetric matrix indexed by the vector of polynomials of the basis basis.

source
SumOfSquares.GramMatrixAttributeType
GramMatrixAttribute(N)
+GramMatrixAttribute()

A constraint attribute for the GramMatrix of a constraint, that is, the positive semidefinite matrix Q indexed by the monomials in the vector X such that $X^\top Q X$ is the sum-of-squares certificate of the constraint.

source
SumOfSquares.gram_operateFunction
gram_operate(::typeof(+), p::GramMatrix, q::GramMatrix)

Computes the Gram matrix equal to the sum between p and q. On the opposite, p + q gives a polynomial equal to p + q. The polynomial p + q can also be obtained by polynomial(gram_operate(+, p, q)).

source
gram_operate(/, p::GramMatrix, α)

Computes the Gram matrix equal to p / α. On the opposite, p / α gives a polynomial equal to p / α. The polynomial p / α can also be obtained by polynomial(gram_operate(/, p, α)).

source
SumOfSquares.LagrangianMultipliersType
LagrangianMultipliers(N)
+LagrangianMultipliers()

A constraint attribute fot the LagrangianMultipliers associated to the inequalities of the domain of a constraint. There is one multiplier per inequality and no multiplier for equalities as the equalities are handled by reducing the polynomials over the ideal they generate instead of explicitely creating multipliers.

source

Bridges are automatically added using the following utilities:

PolyJuMP.bridgeableFunction
bridgeable(c::JuMP.AbstractConstraint, S::Type{<:MOI.AbstractSet})

Wrap the constraint c in JuMP.BridgeableConstraints that may be needed to bridge variables constrained in S on creation.

bridgeable(c::JuMP.AbstractConstraint, F::Type{<:MOI.AbstractFunction},
+           S::Type{<:MOI.AbstractSet})

Wrap the constraint c in JuMP.BridgeableConstraints that may be needed to bridge F-in-S constraints.

source
PolyJuMP.bridgesFunction
bridges(F::Type{<:MOI.AbstractFunction}, S::Type{<:MOI.AbstractSet})

Return a list of bridges that may be needed to bridge F-in-S constraints but not the bridges that may be needed by constraints added by the bridges.

source
bridges(S::Type{<:MOI.AbstractSet})

Return a list of bridges that may be needed to bridge variables constrained in S on creation but not the bridges that may be needed by constraints added by the bridges.

source

Chordal extension:

SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.completionFunction
completion(G::Graph, comp::ChordalCompletion)

Return a chordal extension of G and the corresponding maximal cliques.

The algoritm is Algorithm 3 in [BA10] with the GreedyFillIn heuristic of Table I.

[BA10] Bodlaender, Hans L., and Arie MCA Koster. Treewidth computations I. Upper bounds. Information and Computation 208, no. 3 (2010): 259-275. Utrecht University, Utrecht, The Netherlands www.cs.uu.nl

source
completion(G::Graph, comp::ChordalCompletion)

Return a cluster completion of G and the corresponding maximal cliques.

source

Bridges for polynomial optimization

PolyJuMP.ScalarPolynomialFunctionType
struct ScalarPolynomialFunction{T,P<:MP.AbstractPolynomial{T}} <: MOI.AbstractScalarFunction
+    polynomial::P
+    variables::Vector{MOI.VariableIndex}
+end

Defines the polynomial function of the variables variables where the variable variables(p)[i] corresponds to variables[i].

source
PolyJuMP.Bridges.Objective.ToPolynomialBridgeType
ToPolynomialBridge{T}

ToPolynomialBridge implements the following reformulations:

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

where $f(x)$ is a scalar function and $p(x)$ is a polynomial.

Source node

ToPolynomialBridge supports:

  • MOI.ObjectiveFunction{F} where F is a MOI.AbstractScalarFunction for which convert(::Type{PolyJuMP.ScalarPolynomialFunction}, ::Type{F}). That is for instance the case for MOI.VariableIndex, MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction.

Target nodes

ToPolynomialBridge creates:

  • One objective node: MOI.ObjectiveFunction{PolyJuMP.ScalarPolynomialFunction{T}}
source
PolyJuMP.Bridges.Constraint.ToPolynomialBridgeType
ToPolynomialBridge{T,S} <: Bridges.Constraint.AbstractBridge

ToPolynomialBridge implements the following reformulations:

  • $f(x) \in S$ into $p(x) \in S$ where $f(x)$ is a scalar function and $p(x)$ is a polynomial.

Source node

ToPolynomialBridge supports:

  • F in S where F is a MOI.AbstractScalarFunction for which

convert(::Type{PolyJuMP.ScalarPolynomialFunction}, ::Type{F}). That is for instance the case for MOI.VariableIndex, MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction.

Target nodes

ToPolynomialBridge creates:

source

SAGE extension

To use the SAGE cone in place of the Sum-of-Squares cone for an inequality constraints between polynomials, use the following:

import PolyJuMP
+PolyJuMP.setpolymodule!(model, PolyJuMP.SAGE)
PolyJuMP.SAGE.PolynomialsType
struct Polynomials{M<:Union{Nothing,Int,MP.AbstractMonomial}} <: PolyJuMP.PolynomialSet

Sums of AM/GM Exponential for polynomials.

source
PolyJuMP.SAGE.SignomialsType
struct Signomials{M<:Union{Nothing,Int,MP.AbstractMonomial}} <: PolyJuMP.PolynomialSet

Sums of AM/GM Exponential for signomials.

source
PolyJuMP.SAGE.SignomialsBridgeType
SignomialsBridge{T,S,P,F} <: MOI.Bridges.Constraint.AbstractBridge

We use the Signomials Representative SR equation of [MCW21].

[MCW20] Riley Murray, Venkat Chandrasekaran, Adam Wierman "Newton Polytopes and Relative Entropy Optimization" https://arxiv.org/abs/1810.01614 [MCW21] Murray, Riley, Venkat Chandrasekaran, and Adam Wierman. "Signomials and polynomial optimization via relative entropy and partial dualization." Mathematical Programming Computation 13 (2021): 257-295. https://arxiv.org/pdf/1907.00814.pdf

source
PolyJuMP.SAGE.AGEBridgeType
AGEBridge{T,F,G,H} <: MOI.Bridges.Constraint.AbstractBridge

The nonnegativity of x ≥ 0 in

∑ ci x^αi ≥ -c0 x^α0

can be reformulated as

∑ ci exp(αi'y) ≥ -β exp(α0'y)

In any case, it is shown to be equivalent to

∃ ν ≥ 0 s.t. D(ν, exp(1)*c) ≤ β, ∑ νi αi = α0 ∑ νi [CP16, (3)]

where N(ν, λ) = ∑ νj log(νj/λj) is the relative entropy function. The constant exp(1) can also be moved out of D into

∃ ν ≥ 0 s.t. D(ν, c) - ∑ νi ≤ β, ∑ νi αi = α0 ∑ νi [MCW21, (2)]

The relative entropy cone in MOI is (u, v, w) such that D(w, v) ≥ u. Therefore, we can either encode (β, exp(1)*c, ν) [CP16, (3)] or (β + ∑ νi, c, ν) [MCW21, (2)]. In this bridge, we use the second formulation.

Note

A direct application of the Arithmetic-Geometric mean inequality gives

∃ ν ≥ 0 s.t. D(ν, exp(1)*c) ≤ -log(-β), ∑ νi αi = α0, ∑ νi = 1 [CP16, (4)]

which is not jointly convex in (ν, c, β). The key to get the convex formulation [CP16, (3)] or [MCW21, (2)] instead is to use the convex conjugacy between the exponential and the negative entropy functions [CP16, (iv)].

[CP16] Chandrasekaran, Venkat, and Parikshit Shah. "Relative entropy relaxations for signomial optimization." SIAM Journal on Optimization 26.2 (2016): 1147-1173. [MCW21] Murray, Riley, Venkat Chandrasekaran, and Adam Wierman. "Signomials and polynomial optimization via relative entropy and partial dualization." Mathematical Programming Computation 13 (2021): 257-295. https://arxiv.org/pdf/1907.00814.pdf

source

Internal functions

SumOfSquares.Certificate.Symmetry._reorder!Function
_reorder!(F::LinearAlgebra.Schur{T}) where {T}

Given a Schur decomposition of a, reorder it so that its eigenvalues are in in increasing order.

Note that if T<:Real, F.Schur is quasi upper triangular. By (quasi), we mean that there may be nonzero entries in S[i+1,i] representing complex conjugates. In that case, the complex conjugate are permuted together. If T<:Complex, then S is triangular.

source
SumOfSquares.Certificate.Symmetry._rotate_complexFunction
_rotate_complex(A::AbstractMatrix{T}, B::AbstractMatrix{T}; tol = Base.rtoldefault(real(T))) where {T}

Given (quasi) upper triangular matrix A and B that have the eigenvalues in the same order except the complex pairs which may need to be (signed) permuted, returns an othogonal matrix P such that P' * A * P and B have matching low triangular part. The upper triangular part will be dealt with by _sign_diag.

By (quasi), we mean that if S is a Matrix{<:Real}, then there may be nonzero entries in S[i+1,i] representing complex conjugates. If S is a Matrix{<:Complex}, then S is upper triangular so there is nothing to do.

source
PolyJuMP.QCQP._subs_ensure_moi_orderFunction
_subs_ensure_moi_order(p::PolyJuMP.ScalarPolynomialFunction, old, new)

Substitutes old MP.variables(p.polynomial) with new vars, while re-sorting the MOI p.variables to get them in the correct order after substitution.

source
diff --git a/previews/PR347/generated/Extension/certificate.ipynb b/previews/PR347/generated/Extension/certificate.ipynb new file mode 100644 index 000000000..0be973c97 --- /dev/null +++ b/previews/PR347/generated/Extension/certificate.ipynb @@ -0,0 +1,327 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Certificate" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the polynomial optimization problem (a variation from [Lasserre2009; Example 2.2](@cite)) of\n", + "minimizing the polynomial $x^3 - x^2 + 2xy - y^2 + y^3$\n", + "over the polyhedron defined by the inequalities $x \\ge 0, y \\ge 0$ and $x + y \\geq 1$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Basic semialgebraic Set defined by no equality\n3 inequalities\n x ≥ 0\n y ≥ 0\n -2 + y^2 + x^2 ≥ 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x y\n", + "p = x^3 - x^2 + 2x*y - y^2 + y^3 + x^3 * y\n", + "using SumOfSquares\n", + "S = @set x >= 0 && y >= 0 && x^2 + y^2 >= 2" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "Note that SumOfSquares generates a *standard form* SDP (i.e., SDP variables\n", + "and equality constraints) while SCS expects a *geometric form* SDP (i.e.,\n", + "free variables and symmetric matrices depending affinely on these variables\n", + "constrained to belong to the PSD cone).\n", + "JuMP will transform the standard from to the geometric form will create the PSD\n", + "variables as free variables and then constrain then to be PSD.\n", + "While this will work, since the dual of a standard from is in in geometric form,\n", + "dualizing the problem will generate a smaller SDP.\n", + "We use therefore `Dualization.dual_optimizer` so that SCS solves the dual problem." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "#11 (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import SCS\n", + "using Dualization\n", + "solver = dual_optimizer(SCS.Optimizer)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following program searches for the largest lower bound." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 10 Ap: 9.69e-01 Pobj: -1.0000000e+00 Ad: 9.69e-01 Dobj: -1.0000000e+00 \n", + "Success: SDP solved\n", + "Primal objective value: -1.0000000e+00 \n", + "Dual objective value: -1.0000000e+00 \n", + "Relative primal infeasibility: 1.04e-15 \n", + "Relative dual infeasibility: 6.69e-10 \n", + "Real Relative Gap: -3.43e-10 \n", + "XZ Relative Gap: 1.28e-09 \n", + "DIMACS error measures: 1.99e-15 0.00e+00 1.59e-09 0.00e+00 -3.43e-10 1.28e-09\n", + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 11, constraints m: 20\n", + "cones: \t z: primal zero / dual free vars: 1\n", + "\t l: linear vars: 1\n", + "\t s: psd vars: 18, ssize: 3\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 22, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 2.57e+01 1.01e+00 2.00e+06 -1.00e+06 1.00e-01 1.57e-04 \n", + " 25| 1.30e+11 4.45e+10 8.00e+18 -4.00e+18 1.00e-01 3.27e-04 \n", + "------------------------------------------------------------------\n", + "status: unbounded\n", + "timings: total: 3.28e-04s = setup: 5.71e-05s + solve: 2.71e-04s\n", + "\t lin-sys: 1.46e-05s, cones: 1.59e-04s, accel: 1.69e-06s\n", + "------------------------------------------------------------------\n", + "objective = -inf\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(solver)\n", + "@variable(model, α)\n", + "@objective(model, Max, α)\n", + "@constraint(model, c, p >= α, domain = S)\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We can see that the problem is infeasible, meaning that no lower bound was found." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Dual model with SCS attached\n\n* Status\n Result count : 1\n Termination status : INFEASIBLE\n Message from the solver:\n \"unbounded\"\n\n* Candidate solution (result #1)\n Primal status : INFEASIBLE_POINT\n Dual status : INFEASIBILITY_CERTIFICATE\n Objective value : NaN\n Dual objective value : -1.00000e+00\n\n* Work counters\n Solve time (sec) : 3.28403e-04\n" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We now define the Schmüdgen's certificate:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "import MultivariateBases as MB\n", + "const SOS = SumOfSquares\n", + "const SOSC = SOS.Certificate\n", + "struct Schmüdgen{IC <: SOSC.AbstractIdealCertificate, CT <: SOS.SOSLikeCone, BT <: SOS.AbstractPolynomialBasis} <: SOSC.AbstractPreorderCertificate\n", + " ideal_certificate::IC\n", + " cone::CT\n", + " basis::Type{BT}\n", + " maxdegree::Int\n", + "end\n", + "\n", + "SOSC.cone(certificate::Schmüdgen) = certificate.cone\n", + "\n", + "function SOSC.preprocessed_domain(::Schmüdgen, domain::BasicSemialgebraicSet, p)\n", + " return SOSC.with_variables(domain, p)\n", + "end\n", + "\n", + "function SOSC.preorder_indices(::Schmüdgen, domain::SOSC.WithVariables)\n", + " n = length(domain.inner.p)\n", + " if n >= Sys.WORD_SIZE\n", + " error(\"There are $(2^n - 1) products in Schmüdgen's certificate, they cannot even be indexed with `$Int`.\")\n", + " end\n", + " return map(SOSC.PreorderIndex, 1:(2^n-1))\n", + "end\n", + "\n", + "function SOSC.multiplier_basis(certificate::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables)\n", + " q = SOSC.generator(certificate, index, domain)\n", + " return SOSC.maxdegree_gram_basis(certificate.basis, variables(domain), SOSC.multiplier_maxdegree(certificate.maxdegree, q))\n", + "end\n", + "function SOSC.multiplier_basis_type(::Type{Schmüdgen{IC, CT, BT}}) where {IC, CT, BT}\n", + " return BT\n", + "end\n", + "\n", + "function SOSC.generator(::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables)\n", + " I = [i for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))]\n", + " return prod([domain.inner.p[i] for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))])\n", + "end\n", + "\n", + "SOSC.ideal_certificate(certificate::Schmüdgen) = certificate.ideal_certificate\n", + "SOSC.ideal_certificate(::Type{<:Schmüdgen{IC}}) where {IC} = IC\n", + "\n", + "SOS.matrix_cone_type(::Type{<:Schmüdgen{IC, CT}}) where {IC, CT} = SOS.matrix_cone_type(CT)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Let's try again with our the Schmüdgen certificate:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 15, constraints m: 49\n", + "cones: \t z: primal zero / dual free vars: 1\n", + "\t l: linear vars: 3\n", + "\t s: psd vars: 45, ssize: 5\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 67, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 8.53e+00 5.66e-01 3.99e+01 -2.00e+01 1.00e-01 1.99e-04 \n", + " 250| 1.40e-03 5.14e-05 7.85e-06 8.28e-01 1.00e-01 3.97e-03 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 3.97e-03s = setup: 8.59e-05s + solve: 3.89e-03s\n", + "\t lin-sys: 2.45e-04s, cones: 3.34e-03s, accel: 4.25e-05s\n", + "------------------------------------------------------------------\n", + "objective = 0.828440\n", + "------------------------------------------------------------------\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Dual model with SCS attached\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"solved\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 8.28436e-01\n Dual objective value : 8.28444e-01\n\n* Work counters\n Solve time (sec) : 3.97378e-03\n" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(solver)\n", + "@variable(model, α)\n", + "@objective(model, Max, α)\n", + "ideal_certificate = SOSC.Newton(SOSCone(), MB.MonomialBasis, tuple())\n", + "certificate = Schmüdgen(ideal_certificate, SOSCone(), MB.MonomialBasis, maxdegree(p))\n", + "@constraint(model, c, p >= α, domain = S, certificate = certificate)\n", + "optimize!(model)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Extension/certificate.jl b/previews/PR347/generated/Extension/certificate.jl new file mode 100644 index 000000000..559f3003a --- /dev/null +++ b/previews/PR347/generated/Extension/certificate.jl @@ -0,0 +1,70 @@ +using DynamicPolynomials +@polyvar x y +p = x^3 - x^2 + 2x*y - y^2 + y^3 + x^3 * y +using SumOfSquares +S = @set x >= 0 && y >= 0 && x^2 + y^2 >= 2 + +import SCS +using Dualization +solver = dual_optimizer(SCS.Optimizer) + +model = SOSModel(solver) +@variable(model, α) +@objective(model, Max, α) +@constraint(model, c, p >= α, domain = S) +optimize!(model) + +solution_summary(model) + +import MultivariateBases as MB +const SOS = SumOfSquares +const SOSC = SOS.Certificate +struct Schmüdgen{IC <: SOSC.AbstractIdealCertificate, CT <: SOS.SOSLikeCone, BT <: SOS.AbstractPolynomialBasis} <: SOSC.AbstractPreorderCertificate + ideal_certificate::IC + cone::CT + basis::Type{BT} + maxdegree::Int +end + +SOSC.cone(certificate::Schmüdgen) = certificate.cone + +function SOSC.preprocessed_domain(::Schmüdgen, domain::BasicSemialgebraicSet, p) + return SOSC.with_variables(domain, p) +end + +function SOSC.preorder_indices(::Schmüdgen, domain::SOSC.WithVariables) + n = length(domain.inner.p) + if n >= Sys.WORD_SIZE + error("There are $(2^n - 1) products in Schmüdgen's certificate, they cannot even be indexed with `$Int`.") + end + return map(SOSC.PreorderIndex, 1:(2^n-1)) +end + +function SOSC.multiplier_basis(certificate::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables) + q = SOSC.generator(certificate, index, domain) + return SOSC.maxdegree_gram_basis(certificate.basis, variables(domain), SOSC.multiplier_maxdegree(certificate.maxdegree, q)) +end +function SOSC.multiplier_basis_type(::Type{Schmüdgen{IC, CT, BT}}) where {IC, CT, BT} + return BT +end + +function SOSC.generator(::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables) + I = [i for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))] + return prod([domain.inner.p[i] for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))]) +end + +SOSC.ideal_certificate(certificate::Schmüdgen) = certificate.ideal_certificate +SOSC.ideal_certificate(::Type{<:Schmüdgen{IC}}) where {IC} = IC + +SOS.matrix_cone_type(::Type{<:Schmüdgen{IC, CT}}) where {IC, CT} = SOS.matrix_cone_type(CT) + +model = SOSModel(solver) +@variable(model, α) +@objective(model, Max, α) +ideal_certificate = SOSC.Newton(SOSCone(), MB.MonomialBasis, tuple()) +certificate = Schmüdgen(ideal_certificate, SOSCone(), MB.MonomialBasis, maxdegree(p)) +@constraint(model, c, p >= α, domain = S, certificate = certificate) +optimize!(model) +solution_summary(model) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Extension/certificate/index.html b/previews/PR347/generated/Extension/certificate/index.html new file mode 100644 index 000000000..c22274b79 --- /dev/null +++ b/previews/PR347/generated/Extension/certificate/index.html @@ -0,0 +1,130 @@ + +Certificate · SumOfSquares

Certificate

Contributed by: Benoît Legat

Introduction

Consider the polynomial optimization problem (a variation from (Lasserre, 2009; Example 2.2)) of minimizing the polynomial $x^3 - x^2 + 2xy - y^2 + y^3$ over the polyhedron defined by the inequalities $x \ge 0, y \ge 0$ and $x + y \geq 1$.

using DynamicPolynomials
+@polyvar x y
+p = x^3 - x^2 + 2x*y - y^2 + y^3 + x^3 * y
+using SumOfSquares
+S = @set x >= 0 && y >= 0 && x^2 + y^2 >= 2
Basic semialgebraic Set defined by no equality
+3 inequalities
+ x ≥ 0
+ y ≥ 0
+ -2 + y^2 + x^2 ≥ 0
+

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices. Note that SumOfSquares generates a standard form SDP (i.e., SDP variables and equality constraints) while SCS expects a geometric form SDP (i.e., free variables and symmetric matrices depending affinely on these variables constrained to belong to the PSD cone). JuMP will transform the standard from to the geometric form will create the PSD variables as free variables and then constrain then to be PSD. While this will work, since the dual of a standard from is in in geometric form, dualizing the problem will generate a smaller SDP. We use therefore Dualization.dual_optimizer so that SCS solves the dual problem.

import SCS
+using Dualization
+solver = dual_optimizer(SCS.Optimizer)
#11 (generic function with 1 method)

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following program searches for the largest lower bound.

model = SOSModel(solver)
+@variable(model, α)
+@objective(model, Max, α)
+@constraint(model, c, p >= α, domain = S)
+optimize!(model)
Success: SDP solved
+Primal objective value: 0.0000000e+00
+Dual objective value: 0.0000000e+00
+Relative primal infeasibility: 4.15e-17
+Relative dual infeasibility: 5.00e-11
+Real Relative Gap: 0.00e+00
+XZ Relative Gap: 3.63e-10
+DIMACS error measures: 6.34e-17 0.00e+00 5.00e-11 0.00e+00 0.00e+00 3.63e-10
+------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 11, constraints m: 20
+cones: 	  z: primal zero / dual free vars: 1
+	  l: linear vars: 1
+	  s: psd vars: 18, ssize: 3
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 22, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 2.57e+01  1.01e+00  2.00e+06 -1.00e+06  1.00e-01  1.83e-04
+    25| 1.30e+11  4.45e+10  8.00e+18 -4.00e+18  1.00e-01  3.54e-04
+------------------------------------------------------------------
+status:  unbounded
+timings: total: 3.55e-04s = setup: 6.77e-05s + solve: 2.87e-04s
+	 lin-sys: 1.52e-05s, cones: 1.59e-04s, accel: 1.73e-06s
+------------------------------------------------------------------
+objective = -inf
+------------------------------------------------------------------

We can see that the problem is infeasible, meaning that no lower bound was found.

solution_summary(model)
* Solver : Dual model with SCS attached
+
+* Status
+  Result count       : 1
+  Termination status : INFEASIBLE
+  Message from the solver:
+  "unbounded"
+
+* Candidate solution (result #1)
+  Primal status      : INFEASIBLE_POINT
+  Dual status        : INFEASIBILITY_CERTIFICATE
+  Objective value    : NaN
+  Dual objective value : -1.00000e+00
+
+* Work counters
+  Solve time (sec)   : 3.55034e-04
+

We now define the Schmüdgen's certificate:

import MultivariateBases as MB
+const SOS = SumOfSquares
+const SOSC = SOS.Certificate
+struct Schmüdgen{IC <: SOSC.AbstractIdealCertificate, CT <: SOS.SOSLikeCone, BT <: SOS.AbstractPolynomialBasis} <: SOSC.AbstractPreorderCertificate
+    ideal_certificate::IC
+    cone::CT
+    basis::Type{BT}
+    maxdegree::Int
+end
+
+SOSC.cone(certificate::Schmüdgen) = certificate.cone
+
+function SOSC.preprocessed_domain(::Schmüdgen, domain::BasicSemialgebraicSet, p)
+    return SOSC.with_variables(domain, p)
+end
+
+function SOSC.preorder_indices(::Schmüdgen, domain::SOSC.WithVariables)
+    n = length(domain.inner.p)
+    if n >= Sys.WORD_SIZE
+        error("There are $(2^n - 1) products in Schmüdgen's certificate, they cannot even be indexed with `$Int`.")
+    end
+    return map(SOSC.PreorderIndex, 1:(2^n-1))
+end
+
+function SOSC.multiplier_basis(certificate::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables)
+    q = SOSC.generator(certificate, index, domain)
+    return SOSC.maxdegree_gram_basis(certificate.basis, variables(domain), SOSC.multiplier_maxdegree(certificate.maxdegree, q))
+end
+function SOSC.multiplier_basis_type(::Type{Schmüdgen{IC, CT, BT}}) where {IC, CT, BT}
+    return BT
+end
+
+function SOSC.generator(::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables)
+    I = [i for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))]
+    return prod([domain.inner.p[i] for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))])
+end
+
+SOSC.ideal_certificate(certificate::Schmüdgen) = certificate.ideal_certificate
+SOSC.ideal_certificate(::Type{<:Schmüdgen{IC}}) where {IC} = IC
+
+SOS.matrix_cone_type(::Type{<:Schmüdgen{IC, CT}}) where {IC, CT} = SOS.matrix_cone_type(CT)

Let's try again with our the Schmüdgen certificate:

model = SOSModel(solver)
+@variable(model, α)
+@objective(model, Max, α)
+ideal_certificate = SOSC.Newton(SOSCone(), MB.MonomialBasis, tuple())
+certificate = Schmüdgen(ideal_certificate, SOSCone(), MB.MonomialBasis, maxdegree(p))
+@constraint(model, c, p >= α, domain = S, certificate = certificate)
+optimize!(model)
+solution_summary(model)
* Solver : Dual model with SCS attached
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "solved"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 8.28436e-01
+  Dual objective value : 8.28444e-01
+
+* Work counters
+  Solve time (sec)   : 3.96456e-03
+

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Extension/hypercube.ipynb b/previews/PR347/generated/Extension/hypercube.ipynb new file mode 100644 index 000000000..f9362c690 --- /dev/null +++ b/previews/PR347/generated/Extension/hypercube.ipynb @@ -0,0 +1,345 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Hypercube" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Given a Sum-of-Squares constraint on an algebraic set:\n", + "$$\n", + "g_1(x) = , \\ldots, g_m(x) = 0 \\Rightarrow p(x) \\ge 0.\n", + "$$\n", + "We can either use the certificate:\n", + "$$\n", + "p(x) = s(x) + \\lambda_1(x) g_1(x) + \\cdots + \\lambda_m(x) g_m(x), s_0(x) \\text{ is SOS},\n", + "$$\n", + "or\n", + "$$\n", + "p(x) \\equiv s(x) \\pmod{\\la g_1(x), \\ldots, g_m(x) \\ra}, s_0(x) \\text{ is SOS}.\n", + "$$\n", + "the second one leads to a *simpler* SDP but needs to compute a *Gr\\\"obner* basis:\n", + " * SemialgebraicSets implements Buchberger's algorithm.\n", + " * The `@set` macro recognizes variable fix, e.g., `x = 1`\n", + " and provides shortcut.\n", + " * If you know a \\alert{better} way to take modulo,\n", + " better create your \\alert{own} type of algebraic set!" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We illustrate this in this example." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Algebraic Set defined by 3 equalities\n -1//1 + x[1]^2 = 0\n -1//1 + x[2]^2 = 0\n -1//1 + x[3]^2 = 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:3]\n", + "p = sum(x)^2\n", + "using SumOfSquares\n", + "S = algebraicset([xi^2 - 1 for xi in x])" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We will now search for the minimum of `x` over `S` using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "termination_status(model) = MathOptInterface.OPTIMAL\n", + "objective_value(model) = -4.404406006575101e-10\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-4.404406006575101e-10" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "\n", + "function min_algebraic(S)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = S)\n", + " optimize!(model)\n", + " @show termination_status(model)\n", + " @show objective_value(model)\n", + "end\n", + "\n", + "min_algebraic(S)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "Note that the minimum is in fact `1`.\n", + "Indeed, since each variables is odd (it is either `-1` or `1`)\n", + "and there is an odd number of variables, their sum is odd.\n", + "Therefore it cannot be zero!" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We can see that the Gröbner basis of `S` was computed" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "S.I.gröbner_basis = false\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Buchberger(1.4901161193847656e-8, SemialgebraicSets.presort!, SemialgebraicSets.normal_selection)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "@show S.I.gröbner_basis\n", + "S.I.algo" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The Gröbner basis is simple to compute in this case as the vector\n", + "of `xi^2 - 1` is already a Gröbner basis.\n", + "However, we still need to divide polynomials by the Gröbner basis\n", + "which can be simplified in this case." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "termination_status(model) = MathOptInterface.OPTIMAL\n", + "objective_value(model) = -4.404406006575101e-10\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-4.404406006575101e-10" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "const MP = MultivariatePolynomials\n", + "const SS = SemialgebraicSets\n", + "struct HypercubeIdeal{V} <: SS.AbstractPolynomialIdeal\n", + " variables::Vector{V}\n", + "end\n", + "struct HypercubeSet{V} <: SS.AbstractAlgebraicSet\n", + " ideal::HypercubeIdeal{V}\n", + "end\n", + "MP.variables(set::HypercubeSet) = MP.variables(set.ideal)\n", + "MP.variables(ideal::HypercubeIdeal) = ideal.variables\n", + "Base.similar(set::HypercubeSet, ::Type) = set\n", + "SS.ideal(set::HypercubeSet) = set.ideal\n", + "function Base.rem(p, set::HypercubeIdeal)\n", + " return MP.polynomial(map(MP.terms(p)) do term\n", + " mono = MP.monomial(term)\n", + " new_mono = one(mono)\n", + " for (var, exp) in powers(mono)\n", + " if var in set.variables\n", + " exp = rem(exp, 2)\n", + " end\n", + " new_mono *= var^exp\n", + " end\n", + " MP.coefficient(term) * new_mono\n", + " end)\n", + "end\n", + "\n", + "H = HypercubeSet(HypercubeIdeal(x))\n", + "\n", + "min_algebraic(H)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Let's now try to find the correct lower bound:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "min_algebraic_rational (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "function min_algebraic_rational(S, d)\n", + " model = SOSModel(solver)\n", + " @variable(model, q, SOSPoly(MP.monomials(x, 0:d)))\n", + " deno = q + 1\n", + " @constraint(model, c, deno * p >= deno, domain = S)\n", + " optimize!(model)\n", + " @show termination_status(model)\n", + "end" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "With `d = 0`, it's the same as previously" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "termination_status(model) = MathOptInterface.INFEASIBLE\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "INFEASIBLE::TerminationStatusCode = 2" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "min_algebraic_rational(H, 0)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "But with `d = 1`, we can find the correct lower bound" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "termination_status(model) = MathOptInterface.OPTIMAL\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "OPTIMAL::TerminationStatusCode = 1" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "min_algebraic_rational(H, 1)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Extension/hypercube.jl b/previews/PR347/generated/Extension/hypercube.jl new file mode 100644 index 000000000..a7b52f0a8 --- /dev/null +++ b/previews/PR347/generated/Extension/hypercube.jl @@ -0,0 +1,68 @@ +using DynamicPolynomials +@polyvar x[1:3] +p = sum(x)^2 +using SumOfSquares +S = algebraicset([xi^2 - 1 for xi in x]) + +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + +function min_algebraic(S) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = S) + optimize!(model) + @show termination_status(model) + @show objective_value(model) +end + +min_algebraic(S) + +@show S.I.gröbner_basis +S.I.algo + +const MP = MultivariatePolynomials +const SS = SemialgebraicSets +struct HypercubeIdeal{V} <: SS.AbstractPolynomialIdeal + variables::Vector{V} +end +struct HypercubeSet{V} <: SS.AbstractAlgebraicSet + ideal::HypercubeIdeal{V} +end +MP.variables(set::HypercubeSet) = MP.variables(set.ideal) +MP.variables(ideal::HypercubeIdeal) = ideal.variables +Base.similar(set::HypercubeSet, ::Type) = set +SS.ideal(set::HypercubeSet) = set.ideal +function Base.rem(p, set::HypercubeIdeal) + return MP.polynomial(map(MP.terms(p)) do term + mono = MP.monomial(term) + new_mono = one(mono) + for (var, exp) in powers(mono) + if var in set.variables + exp = rem(exp, 2) + end + new_mono *= var^exp + end + MP.coefficient(term) * new_mono + end) +end + +H = HypercubeSet(HypercubeIdeal(x)) + +min_algebraic(H) + +function min_algebraic_rational(S, d) + model = SOSModel(solver) + @variable(model, q, SOSPoly(MP.monomials(x, 0:d))) + deno = q + 1 + @constraint(model, c, deno * p >= deno, domain = S) + optimize!(model) + @show termination_status(model) +end + +min_algebraic_rational(H, 0) + +min_algebraic_rational(H, 1) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Extension/hypercube/index.html b/previews/PR347/generated/Extension/hypercube/index.html new file mode 100644 index 000000000..a0517d030 --- /dev/null +++ b/previews/PR347/generated/Extension/hypercube/index.html @@ -0,0 +1,59 @@ + +Hypercube · SumOfSquares

Hypercube

Contributed by: Benoît Legat

Given a Sum-of-Squares constraint on an algebraic set:

\[g_1(x) = , \ldots, g_m(x) = 0 \Rightarrow p(x) \ge 0.\]

We can either use the certificate:

\[p(x) = s(x) + \lambda_1(x) g_1(x) + \cdots + \lambda_m(x) g_m(x), s_0(x) \text{ is SOS},\]

or

\[p(x) \equiv s(x) \pmod{\la g_1(x), \ldots, g_m(x) \ra}, s_0(x) \text{ is SOS}.\]

the second one leads to a simpler SDP but needs to compute a Gr\"obner basis:

  • SemialgebraicSets implements Buchberger's algorithm.
  • The @set macro recognizes variable fix, e.g., x = 1 and provides shortcut.
  • If you know a \alert{better} way to take modulo, better create your \alert{own} type of algebraic set!

We illustrate this in this example.

using DynamicPolynomials
+@polyvar x[1:3]
+p = sum(x)^2
+using SumOfSquares
+S = algebraicset([xi^2 - 1 for xi in x])
Algebraic Set defined by 3 equalities
+ -1//1 + x[1]^2 = 0
+ -1//1 + x[2]^2 = 0
+ -1//1 + x[3]^2 = 0
+

We will now search for the minimum of x over S using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+
+function min_algebraic(S)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = S)
+    optimize!(model)
+    @show termination_status(model)
+    @show objective_value(model)
+end
+
+min_algebraic(S)
-4.404406006575101e-10

Note that the minimum is in fact 1. Indeed, since each variables is odd (it is either -1 or 1) and there is an odd number of variables, their sum is odd. Therefore it cannot be zero!

We can see that the Gröbner basis of S was computed

@show S.I.gröbner_basis
+S.I.algo
Buchberger(1.4901161193847656e-8, SemialgebraicSets.presort!, SemialgebraicSets.normal_selection)

The Gröbner basis is simple to compute in this case as the vector of xi^2 - 1 is already a Gröbner basis. However, we still need to divide polynomials by the Gröbner basis which can be simplified in this case.

const MP = MultivariatePolynomials
+const SS = SemialgebraicSets
+struct HypercubeIdeal{V} <: SS.AbstractPolynomialIdeal
+    variables::Vector{V}
+end
+struct HypercubeSet{V} <: SS.AbstractAlgebraicSet
+    ideal::HypercubeIdeal{V}
+end
+MP.variables(set::HypercubeSet) = MP.variables(set.ideal)
+MP.variables(ideal::HypercubeIdeal) = ideal.variables
+Base.similar(set::HypercubeSet, ::Type) = set
+SS.ideal(set::HypercubeSet) = set.ideal
+function Base.rem(p, set::HypercubeIdeal)
+    return MP.polynomial(map(MP.terms(p)) do term
+        mono = MP.monomial(term)
+        new_mono = one(mono)
+        for (var, exp) in powers(mono)
+            if var in set.variables
+                exp = rem(exp, 2)
+            end
+            new_mono *= var^exp
+        end
+        MP.coefficient(term) * new_mono
+    end)
+end
+
+H = HypercubeSet(HypercubeIdeal(x))
+
+min_algebraic(H)
-4.404406006575101e-10

Let's now try to find the correct lower bound:

function min_algebraic_rational(S, d)
+    model = SOSModel(solver)
+    @variable(model, q, SOSPoly(MP.monomials(x, 0:d)))
+    deno = q + 1
+    @constraint(model, c, deno * p >= deno, domain = S)
+    optimize!(model)
+    @show termination_status(model)
+end
min_algebraic_rational (generic function with 1 method)

With d = 0, it's the same as previously

min_algebraic_rational(H, 0)
INFEASIBLE::TerminationStatusCode = 2

But with d = 1, we can find the correct lower bound

min_algebraic_rational(H, 1)
OPTIMAL::TerminationStatusCode = 1

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Extension/typed.ipynb b/previews/PR347/generated/Extension/typed.ipynb new file mode 100644 index 000000000..3d52418b0 --- /dev/null +++ b/previews/PR347/generated/Extension/typed.ipynb @@ -0,0 +1,376 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Multivariate polynomials implementations" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The SumOfSquares package is built on top of the [MultivariatePolynomials](https://github.com/JuliaAlgebra/MultivariatePolynomials.jl)\n", + "abstract interface. [DynamicPolynomials](https://github.com/JuliaAlgebra/DynamicPolynomials.jl/)\n", + "is an implementation of this abstract interface so it can be used with\n", + "SumOfSquares. Moreover, any other implementation can be used as well. To\n", + "illustrate, we solve Examples 3.38 of [BPT12] with\n", + "[TypedPolynomials](https://github.com/JuliaAlgebra/TypedPolynomials.jl),\n", + "another implementation of [MultivariatePolynomials](https://github.com/JuliaAlgebra/MultivariatePolynomials.jl).\n", + "\n", + "[BPT12] Blekherman, G. & Parrilo, P. A. & Thomas, R. R.\n", + "*Semidefinite Optimization and Convex Algebraic Geometry*.\n", + "Society for Industrial and Applied Mathematics, **2012**." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 7.39e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 9.2771541e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 5.3405053e+01 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 0.00000e+00\n Dual objective value : 0.00000e+00\n\n* Work counters\n Solve time (sec) : 4.35114e-04\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "import TypedPolynomials\n", + "TypedPolynomials.@polyvar x y\n", + "using SumOfSquares\n", + "import CSDP\n", + "model = SOSModel(CSDP.Optimizer)\n", + "con_ref = @constraint(model, 2x^4 + 5y^4 - x^2*y^2 >= -2(x^3*y + x + 1))\n", + "optimize!(model)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We see that the problem is feasible. The Sum-of-Squares decomposition can be\n", + "obtained as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-0.6797543969221541 - 0.09754507709792246*y - 0.4175950563713448*x + 2.1931518901396174*y^2 - 0.1269606244678339*x*y - 0.8025867547845221*x^2)^2 + (0.9043573827480671 - 0.6455003192597278*y + 0.2742159536999832*x - 0.10770174782358159*y^2 - 1.2293138068800717*x*y - 0.9300160939847*x^2)^2 + (-0.5739168240154698 - 1.38535050221548*y - 0.6219655378569912*x - 0.2040924100740057*y^2 - 0.15182215880489783*x*y + 0.4443832632766482*x^2)^2 + (0.5703021360913615 - 0.5184093413621602*y + 0.3436728787624473*x + 0.2555950605470665*y^2 + 0.7618441294650047*x*y - 0.02090567376761348*x^2)^2 + (0.041400837217767876 + 0.04911040272637946*y - 0.49990658891857337*x - 0.24792145939081137*y^2 + 0.2972445689917418*x*y - 0.5054184235227418*x^2)^2 + (-0.2524531788141328 - 0.06336647012459033*y + 0.253942572224051*x - 0.10018744153048117*y^2 + 0.059601795985895156*x*y - 0.19381241255811912*x^2)^2" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "sos_decomposition(con_ref)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "Why is there several implementations ?\n", + "Depending in the use-case, one implementation may be more appropriate than\n", + "another one. [TypedPolynomials](https://github.com/JuliaAlgebra/TypedPolynomials.jl)\n", + "is faster than [DynamicPolynomials](https://github.com/JuliaAlgebra/DynamicPolynomials.jl/)\n", + "but it requires new compilation whenever the list of variables changes.\n", + "This means that [TypedPolynomials](https://github.com/JuliaAlgebra/TypedPolynomials.jl)\n", + "is not appropriate when the number of variables is dynamic or too large.\n", + "However, for a small number of variables, it can be faster.\n", + "When solving Sum-of-Squares programs, the time is mostly taken by the Semidefinite programming solver.\n", + "The time taken by SumOfSquares/JuMP/MathOptInterface are usually negligible\n", + "or it time is taken by manipulation of JuMP or MathOptInterface functions\n", + "therefore using TypedPolynomials over DynamicPolynomials may not make much difference in most cases." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "One case for which using TypedPolynomials might be adequate is when\n", + "using domain defined by equalities (possibly also with inequalities).\n", + "Indeed, in that case, SumOfSquares computes the corresponding Gröbner basis which\n", + "may take a non-negligible amount of time for large systems of equalities." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "To illustrate this, consider the computation of Gröbner basis for the\n", + "following system from [CLO05, p. 17].\n", + "The time taken by TypedPolynomials is below:\n", + "\n", + "[CLO05] Cox, A. David & Little, John & O'Shea, Donal\n", + "*Using Algebraic Geometry*.\n", + "Graduate Texts in Mathematics, **2005**.\n", + "https://doi.org/10.1007/b138611" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 284.361 μs (6275 allocations: 1.33 MiB)\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "true" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "using BenchmarkTools\n", + "@btime let\n", + " TypedPolynomials.@polyvar x y\n", + " S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y\n", + " SemialgebraicSets.compute_gröbner_basis!(S.I)\n", + "end" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The time taken by DynamicPolynomials is as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 430.835 μs (8486 allocations: 1.21 MiB)\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "true" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "import DynamicPolynomials\n", + "@btime let\n", + " DynamicPolynomials.@polyvar x y\n", + " S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y\n", + " SemialgebraicSets.compute_gröbner_basis!(S.I)\n", + "end" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We see that TypedPolynomials is faster.\n", + "The time is still negligible for this small system but for larger systems, choosing TypedPolynomials may be helpful.\n", + "We can use this system in a Sum-of-Squares constraint as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: SDP solved\n", + "Primal objective value: 0.0000000e+00 \n", + "Dual objective value: 0.0000000e+00 \n", + "Relative primal infeasibility: 2.23e-16 \n", + "Relative dual infeasibility: 5.00e-11 \n", + "Real Relative Gap: 0.00e+00 \n", + "XZ Relative Gap: 3.04e-10 \n", + "DIMACS error measures: 2.78e-16 0.00e+00 5.00e-11 0.00e+00 0.00e+00 3.04e-10\n", + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 7.64e-01 Pobj: 0.0000000e+00 Ad: 8.07e-01 Dobj: 2.6104524e+00 \n", + "Iter: 2 Ap: 7.71e-01 Pobj: 0.0000000e+00 Ad: 7.40e-01 Dobj: -5.9089088e-02 \n", + "Iter: 3 Ap: 8.08e-01 Pobj: 0.0000000e+00 Ad: 7.65e-01 Dobj: 5.5548423e-01 \n", + "Iter: 4 Ap: 7.56e-01 Pobj: 0.0000000e+00 Ad: 7.79e-01 Dobj: 4.8507209e-01 \n", + "Iter: 5 Ap: 6.95e-01 Pobj: 0.0000000e+00 Ad: 6.77e-01 Dobj: 4.3029792e-01 \n", + "Iter: 6 Ap: 6.35e-01 Pobj: 0.0000000e+00 Ad: 6.83e-01 Dobj: 2.2138686e-01 \n", + "Iter: 7 Ap: 6.21e-01 Pobj: 0.0000000e+00 Ad: 6.43e-01 Dobj: 1.2987235e-01 \n", + "Iter: 8 Ap: 7.42e-01 Pobj: 0.0000000e+00 Ad: 6.82e-01 Dobj: 6.1465384e-02 \n", + "Iter: 9 Ap: 7.31e-01 Pobj: 0.0000000e+00 Ad: 7.05e-01 Dobj: 2.6277571e-02 \n", + "Iter: 10 Ap: 6.92e-01 Pobj: 0.0000000e+00 Ad: 7.09e-01 Dobj: 1.1328842e-02 \n", + "Iter: 11 Ap: 6.63e-01 Pobj: 0.0000000e+00 Ad: 6.68e-01 Dobj: 5.1235942e-03 \n", + "Iter: 12 Ap: 7.09e-01 Pobj: 0.0000000e+00 Ad: 6.82e-01 Dobj: 2.3589372e-03 \n", + "Iter: 13 Ap: 7.23e-01 Pobj: 0.0000000e+00 Ad: 6.78e-01 Dobj: 1.0697628e-03 \n", + "Iter: 14 Ap: 7.14e-01 Pobj: 0.0000000e+00 Ad: 7.19e-01 Dobj: 4.1890647e-04 \n", + "Iter: 15 Ap: 6.78e-01 Pobj: 0.0000000e+00 Ad: 6.29e-01 Dobj: 2.1668852e-04 \n", + "Iter: 16 Ap: 7.27e-01 Pobj: 0.0000000e+00 Ad: 6.96e-01 Dobj: 8.2523725e-05 \n", + "Iter: 17 Ap: 7.23e-01 Pobj: 0.0000000e+00 Ad: 7.33e-01 Dobj: 3.4575868e-05 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 0.00000e+00\n Dual objective value : 0.00000e+00\n\n* Work counters\n Solve time (sec) : 2.39801e-03\n" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "TypedPolynomials.@polyvar x y\n", + "S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y\n", + "poly = -6x - 4y^3 + 2x*y^2 + 6x^3 - 3y^4 + 13x^2 * y^2\n", + "model = Model(CSDP.Optimizer)\n", + "con_ref = @constraint(model, poly in SOSCone(), domain = S)\n", + "optimize!(model)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We obtain the following decomposition:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-5.120614652559952e-5 + 0.0010584845447259056*y + 0.000340808664933532*x + 8.157919816740142*y^2 - 32.77710962574069*x*y + 29.436684176438884*x^2)^2 + (-1.0587801055835377e-5 + 0.00010602040011976172*y + 0.0010736461776558717*x + 26.098857671706984*y^2 - 16.09375738552047*x*y - 25.152942986047297*x^2)^2 + (2.970207075143178e-5 + 0.000794789039104227*y - 0.00016584049945627324*x - 0.12253485455459644*y^2 - 0.0918840250668785*x*y - 0.06835226465828073*x^2)^2 + (-5.17371414837382e-7 - 0.03721185223726042*y + 0.049797912979844754*x - 0.00016553966856285108*y^2 - 0.00012344309755984585*x*y - 9.081294614806447e-5*x^2)^2" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "dec = sos_decomposition(con_ref, 1e-6)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We can verify that it is correct as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3.616651653303066628549364440784429086672702169380499981343746185302734375e-09 + 7.939328636338026522517119874550896058852417925850321085025102664263115294040558e-08y + 5.937935913909069103493283574397747333233173076923076923076923076923076923076939e-08x - 8.92394073232828134722982582616168656386435031890869140625e-06y² - 1.3343841933410004185756037031751475296914577484130859375e-05xy - 4.9814204763931092811990453128601075150072574615478515625e-06x² - 6.626560426307529875581773618857065836588541666666666666666666666666671272623229e-08y³ - 7.115966675167821146411976466576258341471354166666666666666666666666664363688385e-08xy² - 5.8665363968814893645686847634124205796979367733001708984375e-08x²y + 4.281866075381493339171776404747596153846153846153846153846153846153846153846431e-09y⁴", + "text/latex": "$$ 3.616651653303066628549364440784429086672702169380499981343746185302734375 \\cdot 10^{-09} + 7.939328636338026522517119874550896058852417925850321085025102664263115294040558 \\cdot 10^{-08}y + 5.937935913909069103493283574397747333233173076923076923076923076923076923076939 \\cdot 10^{-08}x - 8.92394073232828134722982582616168656386435031890869140625 \\cdot 10^{-06}y^{2} - 1.3343841933410004185756037031751475296914577484130859375 \\cdot 10^{-05}xy - 4.9814204763931092811990453128601075150072574615478515625 \\cdot 10^{-06}x^{2} - 6.626560426307529875581773618857065836588541666666666666666666666666671272623229 \\cdot 10^{-08}y^{3} - 7.115966675167821146411976466576258341471354166666666666666666666666664363688385 \\cdot 10^{-08}xy^{2} - 5.8665363968814893645686847634124205796979367733001708984375 \\cdot 10^{-08}x^{2}y + 4.281866075381493339171776404747596153846153846153846153846153846153846153846431 \\cdot 10^{-09}y^{4} $$" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "rem(dec - poly, S.I)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "Note that the difference between `dec` and `poly` is larger\n", + "than between the full gram matrix because `dec` is obtained by dropping\n", + "the lowest eigenvalues with the threshold `1e-6`; see `sos_decomposition`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "4.28217951213599115010063358120750987012570476508699357509613037109375e-09 + 2.410877415089833983113631389640975391021362529733242132724859775643865390399207e-09y + 1.900553150755093576243290534386268028846153846153846153846153846154529075482902e-09x + 4.282181762828296545109196813427843153476715087890625e-09y² + 1.317522480004384988205856643617153167724609375e-15xy + 4.28216934307557028915880437125451862812042236328125e-09x² - 4.352074256530613638460636138916015625e-14y³ + 6.128431095930864103138446807861328125e-14xy² + 1.8955670366693766482057981193065643310546875e-13x²y + 4.455098580645146564795420720027043269230769230769230769230769230763767396138843e-09y⁴", + "text/latex": "$$ 4.28217951213599115010063358120750987012570476508699357509613037109375 \\cdot 10^{-09} + 2.410877415089833983113631389640975391021362529733242132724859775643865390399207 \\cdot 10^{-09}y + 1.900553150755093576243290534386268028846153846153846153846153846154529075482902 \\cdot 10^{-09}x + 4.282181762828296545109196813427843153476715087890625 \\cdot 10^{-09}y^{2} + 1.317522480004384988205856643617153167724609375 \\cdot 10^{-15}xy + 4.28216934307557028915880437125451862812042236328125 \\cdot 10^{-09}x^{2} - 4.352074256530613638460636138916015625 \\cdot 10^{-14}y^{3} + 6.128431095930864103138446807861328125 \\cdot 10^{-14}xy^{2} + 1.8955670366693766482057981193065643310546875 \\cdot 10^{-13}x^{2}y + 4.455098580645146564795420720027043269230769230769230769230769230763767396138843 \\cdot 10^{-09}y^{4} $$" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "rem(gram_matrix(con_ref) - poly, S.I)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Extension/typed.jl b/previews/PR347/generated/Extension/typed.jl new file mode 100644 index 000000000..96f698ed2 --- /dev/null +++ b/previews/PR347/generated/Extension/typed.jl @@ -0,0 +1,40 @@ +import TypedPolynomials +TypedPolynomials.@polyvar x y +using SumOfSquares +import CSDP +model = SOSModel(CSDP.Optimizer) +con_ref = @constraint(model, 2x^4 + 5y^4 - x^2*y^2 >= -2(x^3*y + x + 1)) +optimize!(model) +solution_summary(model) + +sos_decomposition(con_ref) + +using BenchmarkTools +@btime let + TypedPolynomials.@polyvar x y + S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y + SemialgebraicSets.compute_gröbner_basis!(S.I) +end + +import DynamicPolynomials +@btime let + DynamicPolynomials.@polyvar x y + S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y + SemialgebraicSets.compute_gröbner_basis!(S.I) +end + +TypedPolynomials.@polyvar x y +S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y +poly = -6x - 4y^3 + 2x*y^2 + 6x^3 - 3y^4 + 13x^2 * y^2 +model = Model(CSDP.Optimizer) +con_ref = @constraint(model, poly in SOSCone(), domain = S) +optimize!(model) +solution_summary(model) + +dec = sos_decomposition(con_ref, 1e-6) + +rem(dec - poly, S.I) + +rem(gram_matrix(con_ref) - poly, S.I) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Extension/typed/index.html b/previews/PR347/generated/Extension/typed/index.html new file mode 100644 index 000000000..2926fbd34 --- /dev/null +++ b/previews/PR347/generated/Extension/typed/index.html @@ -0,0 +1,57 @@ + +Multivariate polynomials implementations · SumOfSquares

Multivariate polynomials implementations

Contributed by: Benoît Legat

The SumOfSquares package is built on top of the MultivariatePolynomials abstract interface. DynamicPolynomials is an implementation of this abstract interface so it can be used with SumOfSquares. Moreover, any other implementation can be used as well. To illustrate, we solve Examples 3.38 of [BPT12] with TypedPolynomials, another implementation of MultivariatePolynomials.

[BPT12] Blekherman, G. & Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

import TypedPolynomials
+TypedPolynomials.@polyvar x y
+using SumOfSquares
+import CSDP
+model = SOSModel(CSDP.Optimizer)
+con_ref = @constraint(model, 2x^4 + 5y^4 - x^2*y^2 >= -2(x^3*y + x + 1))
+optimize!(model)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 0.00000e+00
+  Dual objective value : 0.00000e+00
+
+* Work counters
+  Solve time (sec)   : 5.05209e-04
+

We see that the problem is feasible. The Sum-of-Squares decomposition can be obtained as follows:

sos_decomposition(con_ref)
(-0.6797543969221541 - 0.09754507709792246*y - 0.4175950563713448*x + 2.1931518901396174*y^2 - 0.1269606244678339*x*y - 0.8025867547845221*x^2)^2 + (0.9043573827480671 - 0.6455003192597278*y + 0.2742159536999832*x - 0.10770174782358159*y^2 - 1.2293138068800717*x*y - 0.9300160939847*x^2)^2 + (-0.5739168240154698 - 1.38535050221548*y - 0.6219655378569912*x - 0.2040924100740057*y^2 - 0.15182215880489783*x*y + 0.4443832632766482*x^2)^2 + (0.5703021360913615 - 0.5184093413621602*y + 0.3436728787624473*x + 0.2555950605470665*y^2 + 0.7618441294650047*x*y - 0.02090567376761348*x^2)^2 + (0.041400837217767876 + 0.04911040272637946*y - 0.49990658891857337*x - 0.24792145939081137*y^2 + 0.2972445689917418*x*y - 0.5054184235227418*x^2)^2 + (-0.2524531788141328 - 0.06336647012459033*y + 0.253942572224051*x - 0.10018744153048117*y^2 + 0.059601795985895156*x*y - 0.19381241255811912*x^2)^2

Why is there several implementations ? Depending in the use-case, one implementation may be more appropriate than another one. TypedPolynomials is faster than DynamicPolynomials but it requires new compilation whenever the list of variables changes. This means that TypedPolynomials is not appropriate when the number of variables is dynamic or too large. However, for a small number of variables, it can be faster. When solving Sum-of-Squares programs, the time is mostly taken by the Semidefinite programming solver. The time taken by SumOfSquares/JuMP/MathOptInterface are usually negligible or it time is taken by manipulation of JuMP or MathOptInterface functions therefore using TypedPolynomials over DynamicPolynomials may not make much difference in most cases.

One case for which using TypedPolynomials might be adequate is when using domain defined by equalities (possibly also with inequalities). Indeed, in that case, SumOfSquares computes the corresponding Gröbner basis which may take a non-negligible amount of time for large systems of equalities.

To illustrate this, consider the computation of Gröbner basis for the following system from [CLO05, p. 17]. The time taken by TypedPolynomials is below:

[CLO05] Cox, A. David & Little, John & O'Shea, Donal Using Algebraic Geometry. Graduate Texts in Mathematics, 2005. https://doi.org/10.1007/b138611

using BenchmarkTools
+@btime let
+    TypedPolynomials.@polyvar x y
+    S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y
+    SemialgebraicSets.compute_gröbner_basis!(S.I)
+end
true

The time taken by DynamicPolynomials is as follows:

import DynamicPolynomials
+@btime let
+    DynamicPolynomials.@polyvar x y
+    S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y
+    SemialgebraicSets.compute_gröbner_basis!(S.I)
+end
true

We see that TypedPolynomials is faster. The time is still negligible for this small system but for larger systems, choosing TypedPolynomials may be helpful. We can use this system in a Sum-of-Squares constraint as follows:

TypedPolynomials.@polyvar x y
+S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y
+poly = -6x - 4y^3 + 2x*y^2 + 6x^3 - 3y^4 + 13x^2 * y^2
+model = Model(CSDP.Optimizer)
+con_ref = @constraint(model, poly in SOSCone(), domain = S)
+optimize!(model)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 0.00000e+00
+  Dual objective value : 0.00000e+00
+
+* Work counters
+  Solve time (sec)   : 2.50411e-03
+

We obtain the following decomposition:

dec = sos_decomposition(con_ref, 1e-6)
(-5.120614652559952e-5 + 0.0010584845447259056*y + 0.000340808664933532*x + 8.157919816740142*y^2 - 32.77710962574069*x*y + 29.436684176438884*x^2)^2 + (-1.0587801055835377e-5 + 0.00010602040011976172*y + 0.0010736461776558717*x + 26.098857671706984*y^2 - 16.09375738552047*x*y - 25.152942986047297*x^2)^2 + (2.970207075143178e-5 + 0.000794789039104227*y - 0.00016584049945627324*x - 0.12253485455459644*y^2 - 0.0918840250668785*x*y - 0.06835226465828073*x^2)^2 + (-5.17371414837382e-7 - 0.03721185223726042*y + 0.049797912979844754*x - 0.00016553966856285108*y^2 - 0.00012344309755984585*x*y - 9.081294614806447e-5*x^2)^2

We can verify that it is correct as follows:

rem(dec - poly, S.I)

\[ 3.616651653303066628549364440784429086672702169380499981343746185302734375 \cdot 10^{-09} + 7.939328636338026522517119874550896058852417925850321085025102664263115294040558 \cdot 10^{-08}y + 5.937935913909069103493283574397747333233173076923076923076923076923076923076939 \cdot 10^{-08}x - 8.92394073232828134722982582616168656386435031890869140625 \cdot 10^{-06}y^{2} - 1.3343841933410004185756037031751475296914577484130859375 \cdot 10^{-05}xy - 4.9814204763931092811990453128601075150072574615478515625 \cdot 10^{-06}x^{2} - 6.626560426307529875581773618857065836588541666666666666666666666666671272623229 \cdot 10^{-08}y^{3} - 7.115966675167821146411976466576258341471354166666666666666666666666664363688385 \cdot 10^{-08}xy^{2} - 5.8665363968814893645686847634124205796979367733001708984375 \cdot 10^{-08}x^{2}y + 4.281866075381493339171776404747596153846153846153846153846153846153846153846431 \cdot 10^{-09}y^{4} \]

Note that the difference between dec and poly is larger than between the full gram matrix because dec is obtained by dropping the lowest eigenvalues with the threshold 1e-6; see sos_decomposition.

rem(gram_matrix(con_ref) - poly, S.I)

\[ 4.28217951213599115010063358120750987012570476508699357509613037109375 \cdot 10^{-09} + 2.410877415089833983113631389640975391021362529733242132724859775643865390399207 \cdot 10^{-09}y + 1.900553150755093576243290534386268028846153846153846153846153846154529075482902 \cdot 10^{-09}x + 4.282181762828296545109196813427843153476715087890625 \cdot 10^{-09}y^{2} + 1.317522480004384988205856643617153167724609375 \cdot 10^{-15}xy + 4.28216934307557028915880437125451862812042236328125 \cdot 10^{-09}x^{2} - 4.352074256530613638460636138916015625 \cdot 10^{-14}y^{3} + 6.128431095930864103138446807861328125 \cdot 10^{-14}xy^{2} + 1.8955670366693766482057981193065643310546875 \cdot 10^{-13}x^{2}y + 4.455098580645146564795420720027043269230769230769230769230769230763767396138843 \cdot 10^{-09}y^{4} \]


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Extension/univariate_solver.ipynb b/previews/PR347/generated/Extension/univariate_solver.ipynb new file mode 100644 index 000000000..d71faad28 --- /dev/null +++ b/previews/PR347/generated/Extension/univariate_solver.ipynb @@ -0,0 +1,350 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Univariate Solver" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "When using an SDP solver, the Sum-of-Squares constraint is bridged\n", + "into a semidefinite constraint. This reformulation is done only if the\n", + "solver does not support the Sum-of-Squares constraint. We show in this tutorial how to define a solver that supports such constraint.\n", + "The *same* model with be then solved with or without reformulation depending on the solver." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We consider a solver that would support finding the SOS decomposition\n", + "of nonnegative univariate polynomials." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Main.var\"##22912\".MyUnivariateSolver" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "module MyUnivariateSolver\n", + "\n", + "import LinearAlgebra\n", + "import MathOptInterface as MOI\n", + "import MultivariatePolynomials as MP\n", + "import SumOfSquares as SOS\n", + "\n", + "function decompose(p::MP.AbstractPolynomial, tol=1e-6)\n", + " vars = MP.effective_variables(p)\n", + " if length(vars) != 1\n", + " error(\"$p is not univariate\")\n", + " end\n", + " x = first(vars)\n", + " lead = MP.leading_coefficient(p)\n", + " if !isone(lead)\n", + " p = p / lead\n", + " end\n", + " deg = MP.maxdegree(p)\n", + " if isodd(deg)\n", + " return\n", + " end\n", + " d = div(deg, 2)\n", + " companion = zeros(2d, 2d)\n", + " for i in 0:(2d-1)\n", + " if i > 0\n", + " companion[i + 1, i] = 1.0\n", + " end\n", + " companion[i + 1, end] = -MP.coefficient(p, x^i)\n", + " end\n", + " F = LinearAlgebra.schur(complex(companion))\n", + " q = one(p)\n", + " i = 1\n", + " while i <= length(F.values)\n", + " root = F.values[i]\n", + " q *= (x - root)\n", + " if !isapprox(real(root), real(F.values[i+1]), rtol=tol, atol=tol)\n", + " return # Cannot happen for complex conjugate root so it means that we have a root which does not have an even multiplicity This means that the polynomial is not nonnegative\n", + " end\n", + " i += 2\n", + " end\n", + " q1 = MP.map_coefficients(real, q)\n", + " q2 = MP.map_coefficients(imag, q)\n", + " return SOS.SOSDecomposition([q1, q2])\n", + "end\n", + "\n", + "mutable struct Optimizer <: MOI.AbstractOptimizer\n", + " p::Union{Nothing,MP.AbstractPolynomial}\n", + " decomposition::Union{Nothing,SOS.SOSDecomposition}\n", + " tol::Float64\n", + " function Optimizer()\n", + " return new(nothing, nothing, 1e-6)\n", + " end\n", + "end\n", + "\n", + "MOI.is_empty(optimizer::Optimizer) = optimizer.p === nothing\n", + "function MOI.empty!(optimizer::Optimizer)\n", + " optimizer.p = nothing\n", + " return\n", + "end\n", + "\n", + "function MOI.supports_constraint(::Optimizer, ::Type{<:MOI.VectorAffineFunction}, ::Type{<:SOS.SOSPolynomialSet{SOS.FullSpace}})\n", + " return true\n", + "end\n", + "function MOI.add_constraint(optimizer::Optimizer, func::MOI.VectorAffineFunction, set::SOS.SOSPolynomialSet{SOS.FullSpace})\n", + " if optimizer.p !== nothing\n", + " error(\"Only one constraint is supported\")\n", + " end\n", + " if !isempty(func.terms)\n", + " error(\"Only supports constant polynomials\")\n", + " end\n", + " optimizer.p = MP.polynomial(func.constants, set.monomials)\n", + " return MOI.ConstraintIndex{typeof(func),typeof(set)}(1) # There will be only ever one constraint so the index does not matter.\n", + "end\n", + "\n", + "MOI.supports_incremental_interface(::Optimizer) = true\n", + "function MOI.copy_to(optimizer::Optimizer, model::MOI.ModelLike)\n", + " return MOI.Utilities.default_copy_to(optimizer, model)\n", + "end\n", + "function MOI.optimize!(optimizer::Optimizer)\n", + " optimizer.decomposition = decompose(optimizer.p, optimizer.tol)\n", + "end\n", + "\n", + "function MOI.get(optimizer::Optimizer, ::MOI.TerminationStatus)\n", + " if optimizer.decomposition === nothing\n", + " return MOI.INFEASIBLE\n", + " else\n", + " return MOI.OPTIMAL\n", + " end\n", + "end\n", + "\n", + "function MOI.get(optimizer::Optimizer, ::MOI.PrimalStatus)\n", + " if optimizer.decomposition === nothing\n", + " return MOI.NO_SOLUTION\n", + " else\n", + " return MOI.FEASIBLE_POINT\n", + " end\n", + "end\n", + "\n", + "function MOI.get(optimizer::Optimizer, ::SOS.SOSDecompositionAttribute, ::MOI.ConstraintIndex)\n", + " return optimizer.decomposition\n", + "end\n", + "\n", + "end" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We define the same function both for our new solver and SDP solvers." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "decompose (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "function decompose(p, solver)\n", + " model = Model(solver)\n", + " con = @constraint(model, p in SOSCone())\n", + " optimize!(model)\n", + " @assert primal_status(model) == MOI.FEASIBLE_POINT\n", + " return sos_decomposition(con)\n", + "end" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We consider the following univariate polynomial from\n", + "Example 3.35 of [BPT12].\n", + "\n", + "[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R.\n", + "*Semidefinite Optimization and Convex Algebraic Geometry*.\n", + "Society for Industrial and Applied Mathematics, **2012**." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Using our solver we find the following decomposition in two squares." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-0.9999999999999989 + 2.0000000000000018*x + x^2)^2 + (-2.000000000000003 - 2.0*x)^2" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x\n", + "p = x^4 + 4x^3 + 6x^2 + 4x + 5\n", + "dec = decompose(p, MyUnivariateSolver.Optimizer)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We can verify as follows that it gives a correct decomposition:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "5.000000000000011 + 4.000000000000013x + 6.000000000000009x² + 4.0000000000000036x³ + x⁴", + "text/latex": "$$ 5.000000000000011 + 4.000000000000013x + 6.000000000000009x^{2} + 4.0000000000000036x^{3} + x^{4} $$" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "polynomial(dec)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We can also use a semidefinite solver:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: SDP solved\n", + "Primal objective value: 0.0000000e+00 \n", + "Dual objective value: 0.0000000e+00 \n", + "Relative primal infeasibility: 3.80e-09 \n", + "Relative dual infeasibility: 3.42e-14 \n", + "Real Relative Gap: 0.00e+00 \n", + "XZ Relative Gap: 5.00e-11 \n", + "DIMACS error measures: 4.59e-09 0.00e+00 3.42e-14 0.00e+00 0.00e+00 5.00e-11\n", + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.00e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 2.6555556e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 4.6844813e+00 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "(-1.4271293634654956 - 2.4208468386942927*x - 0.608679682768493*x^2)^2 + (1.7193818199786142 - 0.8390365176838647*x - 0.6942919122813989*x^2)^2 + (0.08383279228081496 - 0.14597477689220884*x + 0.3840153438672542*x^2)^2" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "dec = decompose(p, CSDP.Optimizer)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "The decomposition is different, it is the sum of 3 squares.\n", + "However, it is also valid:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "5.000000000000001 + 3.999999999999997x + 5.9999999999999964x² + 4.000000000000001x³ + 1.0000000000000004x⁴", + "text/latex": "$$ 5.000000000000001 + 3.999999999999997x + 5.9999999999999964x^{2} + 4.000000000000001x^{3} + 1.0000000000000004x^{4} $$" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "polynomial(dec)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Extension/univariate_solver.jl b/previews/PR347/generated/Extension/univariate_solver.jl new file mode 100644 index 000000000..3f77bb2a4 --- /dev/null +++ b/previews/PR347/generated/Extension/univariate_solver.jl @@ -0,0 +1,126 @@ +module MyUnivariateSolver + +import LinearAlgebra +import MathOptInterface as MOI +import MultivariatePolynomials as MP +import SumOfSquares as SOS + +function decompose(p::MP.AbstractPolynomial, tol=1e-6) + vars = MP.effective_variables(p) + if length(vars) != 1 + error("$p is not univariate") + end + x = first(vars) + lead = MP.leading_coefficient(p) + if !isone(lead) + p = p / lead + end + deg = MP.maxdegree(p) + if isodd(deg) + return + end + d = div(deg, 2) + companion = zeros(2d, 2d) + for i in 0:(2d-1) + if i > 0 + companion[i + 1, i] = 1.0 + end + companion[i + 1, end] = -MP.coefficient(p, x^i) + end + F = LinearAlgebra.schur(complex(companion)) + q = one(p) + i = 1 + while i <= length(F.values) + root = F.values[i] + q *= (x - root) + if !isapprox(real(root), real(F.values[i+1]), rtol=tol, atol=tol) + return # Cannot happen for complex conjugate root so it means that we have a root which does not have an even multiplicity This means that the polynomial is not nonnegative + end + i += 2 + end + q1 = MP.map_coefficients(real, q) + q2 = MP.map_coefficients(imag, q) + return SOS.SOSDecomposition([q1, q2]) +end + +mutable struct Optimizer <: MOI.AbstractOptimizer + p::Union{Nothing,MP.AbstractPolynomial} + decomposition::Union{Nothing,SOS.SOSDecomposition} + tol::Float64 + function Optimizer() + return new(nothing, nothing, 1e-6) + end +end + +MOI.is_empty(optimizer::Optimizer) = optimizer.p === nothing +function MOI.empty!(optimizer::Optimizer) + optimizer.p = nothing + return +end + +function MOI.supports_constraint(::Optimizer, ::Type{<:MOI.VectorAffineFunction}, ::Type{<:SOS.SOSPolynomialSet{SOS.FullSpace}}) + return true +end +function MOI.add_constraint(optimizer::Optimizer, func::MOI.VectorAffineFunction, set::SOS.SOSPolynomialSet{SOS.FullSpace}) + if optimizer.p !== nothing + error("Only one constraint is supported") + end + if !isempty(func.terms) + error("Only supports constant polynomials") + end + optimizer.p = MP.polynomial(func.constants, set.monomials) + return MOI.ConstraintIndex{typeof(func),typeof(set)}(1) # There will be only ever one constraint so the index does not matter. +end + +MOI.supports_incremental_interface(::Optimizer) = true +function MOI.copy_to(optimizer::Optimizer, model::MOI.ModelLike) + return MOI.Utilities.default_copy_to(optimizer, model) +end +function MOI.optimize!(optimizer::Optimizer) + optimizer.decomposition = decompose(optimizer.p, optimizer.tol) +end + +function MOI.get(optimizer::Optimizer, ::MOI.TerminationStatus) + if optimizer.decomposition === nothing + return MOI.INFEASIBLE + else + return MOI.OPTIMAL + end +end + +function MOI.get(optimizer::Optimizer, ::MOI.PrimalStatus) + if optimizer.decomposition === nothing + return MOI.NO_SOLUTION + else + return MOI.FEASIBLE_POINT + end +end + +function MOI.get(optimizer::Optimizer, ::SOS.SOSDecompositionAttribute, ::MOI.ConstraintIndex) + return optimizer.decomposition +end + +end + +using SumOfSquares +function decompose(p, solver) + model = Model(solver) + con = @constraint(model, p in SOSCone()) + optimize!(model) + @assert primal_status(model) == MOI.FEASIBLE_POINT + return sos_decomposition(con) +end + +using DynamicPolynomials +@polyvar x +p = x^4 + 4x^3 + 6x^2 + 4x + 5 +dec = decompose(p, MyUnivariateSolver.Optimizer) + +polynomial(dec) + +import CSDP +dec = decompose(p, CSDP.Optimizer) + +polynomial(dec) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Extension/univariate_solver/index.html b/previews/PR347/generated/Extension/univariate_solver/index.html new file mode 100644 index 000000000..875580516 --- /dev/null +++ b/previews/PR347/generated/Extension/univariate_solver/index.html @@ -0,0 +1,115 @@ + +Univariate Solver · SumOfSquares

Univariate Solver

Contributed by: Benoît Legat

When using an SDP solver, the Sum-of-Squares constraint is bridged into a semidefinite constraint. This reformulation is done only if the solver does not support the Sum-of-Squares constraint. We show in this tutorial how to define a solver that supports such constraint. The same model with be then solved with or without reformulation depending on the solver.

We consider a solver that would support finding the SOS decomposition of nonnegative univariate polynomials.

module MyUnivariateSolver
+
+import LinearAlgebra
+import MathOptInterface as MOI
+import MultivariatePolynomials as MP
+import SumOfSquares as SOS
+
+function decompose(p::MP.AbstractPolynomial, tol=1e-6)
+    vars = MP.effective_variables(p)
+    if length(vars) != 1
+        error("$p is not univariate")
+    end
+    x = first(vars)
+    lead = MP.leading_coefficient(p)
+    if !isone(lead)
+        p = p / lead
+    end
+    deg = MP.maxdegree(p)
+    if isodd(deg)
+        return
+    end
+    d = div(deg, 2)
+    companion = zeros(2d, 2d)
+    for i in 0:(2d-1)
+        if i > 0
+            companion[i + 1, i] = 1.0
+        end
+        companion[i + 1, end] = -MP.coefficient(p, x^i)
+    end
+    F = LinearAlgebra.schur(complex(companion))
+    q = one(p)
+    i = 1
+    while i <= length(F.values)
+        root = F.values[i]
+        q *= (x - root)
+        if !isapprox(real(root), real(F.values[i+1]), rtol=tol, atol=tol)
+            return # Cannot happen for complex conjugate root so it means that we have a root which does not have an even multiplicity This means that the polynomial is not nonnegative
+        end
+        i += 2
+    end
+    q1 = MP.map_coefficients(real, q)
+    q2 = MP.map_coefficients(imag, q)
+    return SOS.SOSDecomposition([q1, q2])
+end
+
+mutable struct Optimizer <: MOI.AbstractOptimizer
+    p::Union{Nothing,MP.AbstractPolynomial}
+    decomposition::Union{Nothing,SOS.SOSDecomposition}
+    tol::Float64
+    function Optimizer()
+        return new(nothing, nothing, 1e-6)
+    end
+end
+
+MOI.is_empty(optimizer::Optimizer) = optimizer.p === nothing
+function MOI.empty!(optimizer::Optimizer)
+    optimizer.p = nothing
+    return
+end
+
+function MOI.supports_constraint(::Optimizer, ::Type{<:MOI.VectorAffineFunction}, ::Type{<:SOS.SOSPolynomialSet{SOS.FullSpace}})
+    return true
+end
+function MOI.add_constraint(optimizer::Optimizer, func::MOI.VectorAffineFunction, set::SOS.SOSPolynomialSet{SOS.FullSpace})
+    if optimizer.p !== nothing
+        error("Only one constraint is supported")
+    end
+    if !isempty(func.terms)
+        error("Only supports constant polynomials")
+    end
+    optimizer.p = MP.polynomial(func.constants, set.monomials)
+    return MOI.ConstraintIndex{typeof(func),typeof(set)}(1) # There will be only ever one constraint so the index does not matter.
+end
+
+MOI.supports_incremental_interface(::Optimizer) = true
+function MOI.copy_to(optimizer::Optimizer, model::MOI.ModelLike)
+    return MOI.Utilities.default_copy_to(optimizer, model)
+end
+function MOI.optimize!(optimizer::Optimizer)
+    optimizer.decomposition = decompose(optimizer.p, optimizer.tol)
+end
+
+function MOI.get(optimizer::Optimizer, ::MOI.TerminationStatus)
+    if optimizer.decomposition === nothing
+        return MOI.INFEASIBLE
+    else
+        return MOI.OPTIMAL
+    end
+end
+
+function MOI.get(optimizer::Optimizer, ::MOI.PrimalStatus)
+    if optimizer.decomposition === nothing
+        return MOI.NO_SOLUTION
+    else
+        return MOI.FEASIBLE_POINT
+    end
+end
+
+function MOI.get(optimizer::Optimizer, ::SOS.SOSDecompositionAttribute, ::MOI.ConstraintIndex)
+    return optimizer.decomposition
+end
+
+end
Main.MyUnivariateSolver

We define the same function both for our new solver and SDP solvers.

using SumOfSquares
+function decompose(p, solver)
+    model = Model(solver)
+    con = @constraint(model, p in SOSCone())
+    optimize!(model)
+    @assert primal_status(model) == MOI.FEASIBLE_POINT
+    return sos_decomposition(con)
+end
decompose (generic function with 1 method)

We consider the following univariate polynomial from Example 3.35 of [BPT12].

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

Using our solver we find the following decomposition in two squares.

using DynamicPolynomials
+@polyvar x
+p = x^4 + 4x^3 + 6x^2 + 4x + 5
+dec = decompose(p, MyUnivariateSolver.Optimizer)
(-0.9999999999999989 + 2.0000000000000018*x + x^2)^2 + (-2.000000000000003 - 2.0*x)^2

We can verify as follows that it gives a correct decomposition:

polynomial(dec)

\[ 5.000000000000011 + 4.000000000000013x + 6.000000000000009x^{2} + 4.0000000000000036x^{3} + x^{4} \]

We can also use a semidefinite solver:

import CSDP
+dec = decompose(p, CSDP.Optimizer)
(-1.4271293634654956 - 2.4208468386942927*x - 0.608679682768493*x^2)^2 + (1.7193818199786142 - 0.8390365176838647*x - 0.6942919122813989*x^2)^2 + (0.08383279228081496 - 0.14597477689220884*x + 0.3840153438672542*x^2)^2

The decomposition is different, it is the sum of 3 squares. However, it is also valid:

polynomial(dec)

\[ 5.000000000000001 + 3.999999999999997x + 5.9999999999999964x^{2} + 4.000000000000001x^{3} + 1.0000000000000004x^{4} \]


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/circle.ipynb b/previews/PR347/generated/Getting started/circle.ipynb new file mode 100644 index 000000000..dae0f21dc --- /dev/null +++ b/previews/PR347/generated/Getting started/circle.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Nonnegative over a variety" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The polynomial $1 - y^2$ is nonnegative for all $y$ in the unit circle.\n", + "This can be verified using Sum-of-Squares." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Algebraic Set defined by 1 equalitty\n -1//1 + y^2 + x^2 = 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "using SumOfSquares\n", + "@polyvar x y\n", + "S = @set x^2 + y^2 == 1" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "The domain over which the nonnegativity of $1 - y^2$ should be certified\n", + "is specified through the `domain` keyword argument." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "import CSDP\n", + "model = SOSModel(CSDP.Optimizer)\n", + "set_silent(model)\n", + "con_ref = @constraint(model, 1 - y^2 >= 0, domain = S)\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We can see that the model was feasible:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 0.00000e+00\n Dual objective value : 0.00000e+00\n\n* Work counters\n Solve time (sec) : 2.95200e-02\n" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The certificate can be obtained as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(1.0000000044294615*x)^2" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "sos_decomposition(con_ref, 1e-6)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "It returns $x^2$ which is a valid certificate as:\n", + "$$ 1 - y^2 \\equiv x^2 \\pmod{x^2 + y^2 - 1} $$" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/circle.jl b/previews/PR347/generated/Getting started/circle.jl new file mode 100644 index 000000000..2895de25b --- /dev/null +++ b/previews/PR347/generated/Getting started/circle.jl @@ -0,0 +1,16 @@ +using DynamicPolynomials +using SumOfSquares +@polyvar x y +S = @set x^2 + y^2 == 1 + +import CSDP +model = SOSModel(CSDP.Optimizer) +set_silent(model) +con_ref = @constraint(model, 1 - y^2 >= 0, domain = S) +optimize!(model) + +solution_summary(model) + +sos_decomposition(con_ref, 1e-6) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/circle/index.html b/previews/PR347/generated/Getting started/circle/index.html new file mode 100644 index 000000000..5f3e81dce --- /dev/null +++ b/previews/PR347/generated/Getting started/circle/index.html @@ -0,0 +1,27 @@ + +Nonnegative over a variety · SumOfSquares

Nonnegative over a variety

The polynomial $1 - y^2$ is nonnegative for all $y$ in the unit circle. This can be verified using Sum-of-Squares.

using DynamicPolynomials
+using SumOfSquares
+@polyvar x y
+S = @set x^2 + y^2 == 1
Algebraic Set defined by 1 equalitty
+ -1//1 + y^2 + x^2 = 0
+

We need to pick an SDP solver, see here for a list of the available choices. The domain over which the nonnegativity of $1 - y^2$ should be certified is specified through the domain keyword argument.

import CSDP
+model = SOSModel(CSDP.Optimizer)
+set_silent(model)
+con_ref = @constraint(model, 1 - y^2 >= 0, domain = S)
+optimize!(model)

We can see that the model was feasible:

solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 0.00000e+00
+  Dual objective value : 0.00000e+00
+
+* Work counters
+  Solve time (sec)   : 1.01709e-03
+

The certificate can be obtained as follows:

sos_decomposition(con_ref, 1e-6)
(1.0000000044294615*x)^2

It returns $x^2$ which is a valid certificate as: $ 1 - y^2 \equiv x^2 \pmod{x^2 + y^2 - 1} $


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/dualization.ipynb b/previews/PR347/generated/Getting started/dualization.ipynb new file mode 100644 index 000000000..de20927cc --- /dev/null +++ b/previews/PR347/generated/Getting started/dualization.ipynb @@ -0,0 +1,396 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# On the importance of Dualization" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "using SumOfSquares" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "Sum-of-Squares programs are usually solved by SemiDefinite Programming solvers (SDPs).\n", + "These programs can be represented into two different formats:\n", + "Either the *standard conic form*, also known as *kernel form*:\n", + "$$\n", + "\\begin{aligned}\n", + " \\min\\limits_{Q \\in \\mathbb{S}_n} & \\langle C, Q \\rangle\\\\\n", + " \\text{subject to:} & \\langle A_i, Q \\rangle = b_i, \\quad i=1,2,\\ldots,m\\\\\n", + " & Q \\succeq 0,\n", + "\\end{aligned}\n", + "$$\n", + "or the *geometric conic form*, also known as *image form*:\n", + "$$\n", + "\\begin{aligned}\n", + " \\max\\limits_{y \\in \\mathbb{R}^m} & \\langle b, y \\rangle\\\\\n", + " \\text{subject to:} & C \\succeq \\sum_{i=1}^m A_i y_i\\\\\n", + " & y\\ \\mathsf{free},\n", + "\\end{aligned}\n", + "$$" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "In this tutorial, we investigate in which of these two forms a Sum-of-Squares\n", + "constraint should be written into.\n", + "Consider the simple example of trying to determine whether the following univariate\n", + "polynomial is a Sum-of-Squares:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 6, constraints m: 11\n", + "cones: \t z: primal zero / dual free vars: 5\n", + "\t s: psd vars: 6, ssize: 1\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 12, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 1.30e+01 1.87e+00 2.95e+01 1.47e+01 1.00e-01 2.66e-04 \n", + " 50| 6.01e-07 2.84e-07 1.95e-06 -9.76e-07 1.00e-01 4.26e-04 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 4.27e-04s = setup: 1.12e-04s + solve: 3.15e-04s\n", + "\t lin-sys: 1.91e-05s, cones: 1.80e-04s, accel: 3.97e-06s\n", + "------------------------------------------------------------------\n", + "objective = -0.000001\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "import SCS\n", + "@polyvar x\n", + "p = (x + 1)^2 * (x + 2)^2\n", + "model_scs = Model(SCS.Optimizer)\n", + "con_ref = @constraint(model_scs, p in SOSCone())\n", + "optimize!(model_scs)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "As we can see in the log, SCS reports `6` variables and `11` constraints.\n", + "We can also choose to dualize the problem before it is\n", + "passed to SCS as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 5, constraints m: 6\n", + "cones: \t s: psd vars: 6, ssize: 1\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 6, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 1.97e+02 1.05e+01 4.39e+03 -2.20e+03 1.00e-01 1.39e-04 \n", + " 50| 6.29e-06 1.81e-06 2.22e-05 -1.11e-05 1.00e-01 2.88e-04 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 2.89e-04s = setup: 4.34e-05s + solve: 2.45e-04s\n", + "\t lin-sys: 1.37e-05s, cones: 1.29e-04s, accel: 3.01e-06s\n", + "------------------------------------------------------------------\n", + "objective = -0.000011\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "using Dualization\n", + "model_dual_scs = Model(dual_optimizer(SCS.Optimizer))\n", + "@objective(model_dual_scs, Max, 0.0)\n", + "con_ref = @constraint(model_dual_scs, p in SOSCone())\n", + "optimize!(model_dual_scs)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "This time, SCS reports `5` variables and `6` constraints." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Bridges operating behind the scenes\n", + "\n", + "The difference comes from the fact that, when designing the JuMP interface of\n", + "SCS, it was decided that the model would be read in the image form.\n", + "SCS therefore declares that it only supports free variables, represented in\n", + "JuMP as variables in `MOI.Reals` and affine semidefinite constraints,\n", + "represented in JuMP as\n", + "`MOI.VectorAffineFunction`-in-`MOI.PositiveSemidefiniteConeTriangle`\n", + "constraints.\n", + "On the other hand, SumOfSquares gave the model in kernel form so the\n", + "positive semidefinite (PSD) variables were reformulated as free variables\n", + "constrained to be PSD using an affine PSD constraints.\n", + "\n", + "This transformation is done transparently without warning but it can be\n", + "inspected using `print_active_bridges`.\n", + "As shown below, we can see\n", + "`Unsupported variable: MOI.PositiveSemidefiniteConeTriangle` and\n", + "`adding as constraint`\n", + "indicating that PSD variables are not supported and they are added as free\n", + "variables.\n", + "Then we have `Unsupported constraint: MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle`\n", + "indicating that SCS does not support constraining variables in the PSD cone\n", + "so it will just convert it into affine expressions in the PSD cone.\n", + "Of course, this is equivalent but it means that SCS will not exploit this\n", + "particular structure of the problem hence solving might be less efficient." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " * Supported objective: MOI.ScalarAffineFunction{Float64}\n", + " * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-SumOfSquares.SOSPolynomialSet{FullSpace, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}}\n", + " | bridged by:\n", + " | SumOfSquares.Bridges.Constraint.SOSPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, FullSpace, Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}, Vector{Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}}}}, Union{SumOfSquares.EmptyCone, SumOfSquares.PositiveSemidefinite2x2ConeTriangle, MOI.Nonnegatives, MOI.PositiveSemidefiniteConeTriangle}, MOI.PositiveSemidefiniteConeTriangle, MonomialBasis, MonomialBasis, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}\n", + " | may introduce:\n", + " | * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-PolyJuMP.ZeroPolynomialSet{FullSpace, MonomialBasis, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}\n", + " | | bridged by:\n", + " | | PolyJuMP.Bridges.Constraint.ZeroPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}\n", + " | | may introduce:\n", + " | | * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Zeros\n", + " | * Unsupported variable: SumOfSquares.EmptyCone\n", + " | | adding as constraint:\n", + " | | * Supported variable: MOI.Reals\n", + " | | * Unsupported constraint: MOI.VectorOfVariables-in-SumOfSquares.EmptyCone\n", + " | | | bridged by:\n", + " | | | SumOfSquares.Bridges.Constraint.EmptyBridge{Float64, MOI.VectorOfVariables}\n", + " | | | may introduce:\n", + " | * Unsupported variable: MOI.Nonnegatives\n", + " | | adding as constraint:\n", + " | | * Supported variable: MOI.Reals\n", + " | | * Unsupported constraint: MOI.VectorOfVariables-in-MOI.Nonnegatives\n", + " | | | bridged by:\n", + " | | | MOIB.Constraint.FunctionConversionBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables, MOI.Nonnegatives}\n", + " | | | may introduce:\n", + " | | | * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Nonnegatives\n", + " | * Unsupported variable: SumOfSquares.PositiveSemidefinite2x2ConeTriangle\n", + " | | bridged by:\n", + " | | SumOfSquares.Bridges.Variable.PositiveSemidefinite2x2Bridge{Float64}\n", + " | | may introduce:\n", + " | | * Unsupported variable: MOI.RotatedSecondOrderCone\n", + " | | | adding as constraint:\n", + " | | | * Supported variable: MOI.Reals\n", + " | | | * Unsupported constraint: MOI.VectorOfVariables-in-MOI.RotatedSecondOrderCone\n", + " | | | | bridged by:\n", + " | | | | MOIB.Constraint.RSOCtoSOCBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}\n", + " | | | | may introduce:\n", + " | | | | * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.SecondOrderCone\n", + " | * Unsupported variable: MOI.PositiveSemidefiniteConeTriangle\n", + " | | adding as constraint:\n", + " | | * Supported variable: MOI.Reals\n", + " | | * Unsupported constraint: MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle\n", + " | | | bridged by:\n", + " | | | MOIB.Constraint.SetDotScalingBridge{Float64, MOI.PositiveSemidefiniteConeTriangle, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}\n", + " | | | may introduce:\n", + " | | | * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}\n", + " | | | | bridged by:\n", + " | | | | SCS.ScaledPSDConeBridge{Float64, MOI.VectorAffineFunction{Float64}}\n", + " | | | | may introduce:\n", + " | | | | * Supported constraint: MOI.VectorAffineFunction{Float64}-in-SCS.ScaledPSDCone\n" + ] + } + ], + "cell_type": "code", + "source": [ + "print_active_bridges(model_scs)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "With the dual version, we can see that variables in the PSD cone are supported\n", + "directly hence we don't need that extra conversion." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " * Supported objective: MOI.ScalarAffineFunction{Float64}\n", + " * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-SumOfSquares.SOSPolynomialSet{FullSpace, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}}\n", + " | bridged by:\n", + " | SumOfSquares.Bridges.Constraint.SOSPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, FullSpace, Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}, Vector{Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}}}}, Union{SumOfSquares.EmptyCone, SumOfSquares.PositiveSemidefinite2x2ConeTriangle, MOI.Nonnegatives, MOI.PositiveSemidefiniteConeTriangle}, MOI.PositiveSemidefiniteConeTriangle, MonomialBasis, MonomialBasis, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}\n", + " | may introduce:\n", + " | * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-PolyJuMP.ZeroPolynomialSet{FullSpace, MonomialBasis, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}\n", + " | | bridged by:\n", + " | | PolyJuMP.Bridges.Constraint.ZeroPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}\n", + " | | may introduce:\n", + " | | * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Zeros\n", + " | * Unsupported variable: SumOfSquares.EmptyCone\n", + " | | adding as constraint:\n", + " | | * Supported variable: MOI.Reals\n", + " | | * Unsupported constraint: MOI.VectorOfVariables-in-SumOfSquares.EmptyCone\n", + " | | | bridged by:\n", + " | | | SumOfSquares.Bridges.Constraint.EmptyBridge{Float64, MOI.VectorOfVariables}\n", + " | | | may introduce:\n", + " | * Supported variable: MOI.Nonnegatives\n", + " | * Unsupported variable: SumOfSquares.PositiveSemidefinite2x2ConeTriangle\n", + " | | bridged by:\n", + " | | SumOfSquares.Bridges.Variable.PositiveSemidefinite2x2Bridge{Float64}\n", + " | | may introduce:\n", + " | | * Supported variable: MOI.RotatedSecondOrderCone\n", + " | * Supported variable: MOI.PositiveSemidefiniteConeTriangle\n" + ] + } + ], + "cell_type": "code", + "source": [ + "print_active_bridges(model_dual_scs)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "## In more details\n", + "\n", + "Consider a polynomial\n", + "$$\n", + "p(x) = \\sum_{\\alpha} p_\\alpha x^\\alpha,\n", + "$$\n", + "a vector of monomials `b(x)` and the set\n", + "$$\n", + "\\mathcal{A}_\\alpha = \\{\\,(\\beta, \\gamma) \\in b(x)^2 \\mid x^\\beta x^\\gamma = x^\\alpha\\,\\}\n", + "$$\n", + "The constraint encoding the existence of a PSD matrix `Q` such that `p(x) = b(x)' * Q * b(x)`\n", + "can be written in standard conic form as follows:\n", + "$$\n", + "\\begin{aligned}\n", + " \\langle \\sum_{(\\beta, \\gamma) \\in \\mathcal{A}_\\alpha} e_\\beta e_\\gamma^\\top, Q \\rangle & = p_\\alpha, \\quad\\forall \\alpha\\\\\n", + " Q & \\succeq 0\n", + "\\end{aligned}\n", + "$$\n", + "Given an arbitrary choice of elements in each set $\\mathcal{A}_\\alpha$:\n", + "$(\\beta_\\alpha, \\gamma_\\alpha) \\in \\mathcal{A}_\\alpha$.\n", + "It can also equivalently be written in the geometric conic form as follows:\n", + "$$\n", + "\\begin{aligned}\n", + " p_\\alpha e_{\\beta_\\alpha} e_{\\gamma_\\alpha}^\\top +\n", + " \\sum_{(\\beta, \\gamma) \\in \\mathcal{A}_\\alpha \\setminus (\\beta_\\alpha, \\gamma_\\alpha)}\n", + " y_{\\beta,\\gamma} (e_\\beta e_\\gamma - e_{\\beta_\\alpha} e_{\\gamma_\\alpha}^\\top)^\\top\n", + " & \\succeq 0\\\\\n", + " y_{\\beta,\\gamma} & \\text{ free}\n", + "\\end{aligned}\n", + "$$\n", + "\n", + "## Should I dualize or not ?\n", + "\n", + "Let's study the evolution of the dimensions `m` and `n` of the semidefinite\n", + "program in two extreme examples and then try to extrapolate from these.\n", + "\n", + "### Univariate case\n", + "\n", + "Suppose `p` is a univariate polynomial of degree $2d$.\n", + "Then `n` will be equal to `d(d + 1)/2` for both the standard and geometric conic forms.\n", + "On the other hand, `m` will be equal to `2d + 1` for the standard conic form and\n", + "`d(d + 1) / 2 - (2d + 1)` for the geometric form case.\n", + "So `m` grows **linearly** for the kernel form but **quadratically** for the image form!\n", + "\n", + "### Quadratic case\n", + "\n", + "Suppose `p` is a quadratic form of `d` variables.\n", + "Then `n` will be equal to `d` for both the standard and geometric conic forms.\n", + "On the other hand, `m` will be equal to `d(d + 1)/2` for the standard conic form and\n", + "`0` for the geometric form case.\n", + "So `m` grows **quadratically** for the kernel form but is zero for the image form!\n", + "\n", + "### In general\n", + "\n", + "In general, if $s_d$ is the dimension of the space of polynomials of degree `d` then\n", + "$m = s_{2d}$ for the kernel form and $m = s_{d}(s_{d} + 1)/2 - s_{2d}$ for the image form.\n", + "As a rule of thumb, the kernel form will have a smaller `m` if `p` has a low number of variables\n", + "and low degree and vice versa.\n", + "Of course, you can always try with and without Dualization and see which one works best." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/dualization.jl b/previews/PR347/generated/Getting started/dualization.jl new file mode 100644 index 000000000..f4e5f19fa --- /dev/null +++ b/previews/PR347/generated/Getting started/dualization.jl @@ -0,0 +1,21 @@ +using DynamicPolynomials +using SumOfSquares + +import SCS +@polyvar x +p = (x + 1)^2 * (x + 2)^2 +model_scs = Model(SCS.Optimizer) +con_ref = @constraint(model_scs, p in SOSCone()) +optimize!(model_scs) + +using Dualization +model_dual_scs = Model(dual_optimizer(SCS.Optimizer)) +@objective(model_dual_scs, Max, 0.0) +con_ref = @constraint(model_dual_scs, p in SOSCone()) +optimize!(model_dual_scs) + +print_active_bridges(model_scs) + +print_active_bridges(model_dual_scs) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/dualization/index.html b/previews/PR347/generated/Getting started/dualization/index.html new file mode 100644 index 000000000..497908be3 --- /dev/null +++ b/previews/PR347/generated/Getting started/dualization/index.html @@ -0,0 +1,157 @@ + +On the importance of Dualization · SumOfSquares

On the importance of Dualization

using DynamicPolynomials
+using SumOfSquares

Sum-of-Squares programs are usually solved by SemiDefinite Programming solvers (SDPs). These programs can be represented into two different formats: Either the standard conic form, also known as kernel form:

\[\begin{aligned} + \min\limits_{Q \in \mathbb{S}_n} & \langle C, Q \rangle\\ + \text{subject to:} & \langle A_i, Q \rangle = b_i, \quad i=1,2,\ldots,m\\ + & Q \succeq 0, +\end{aligned}\]

or the geometric conic form, also known as image form:

\[\begin{aligned} + \max\limits_{y \in \mathbb{R}^m} & \langle b, y \rangle\\ + \text{subject to:} & C \succeq \sum_{i=1}^m A_i y_i\\ + & y\ \mathsf{free}, +\end{aligned}\]

In this tutorial, we investigate in which of these two forms a Sum-of-Squares constraint should be written into. Consider the simple example of trying to determine whether the following univariate polynomial is a Sum-of-Squares:

import SCS
+@polyvar x
+p = (x + 1)^2 * (x + 2)^2
+model_scs = Model(SCS.Optimizer)
+con_ref = @constraint(model_scs, p in SOSCone())
+optimize!(model_scs)
Success: SDP solved
+Primal objective value: 0.0000000e+00
+Dual objective value: 0.0000000e+00
+Relative primal infeasibility: 4.15e-17
+Relative dual infeasibility: 5.00e-11
+Real Relative Gap: 0.00e+00
+XZ Relative Gap: 3.63e-10
+DIMACS error measures: 6.34e-17 0.00e+00 5.00e-11 0.00e+00 0.00e+00 3.63e-10
+------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 6, constraints m: 11
+cones: 	  z: primal zero / dual free vars: 5
+	  s: psd vars: 6, ssize: 1
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 12, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 1.30e+01  1.87e+00  2.95e+01  1.47e+01  1.00e-01  1.48e-04
+    50| 6.01e-07  2.84e-07  1.95e-06 -9.76e-07  1.00e-01  3.01e-04
+------------------------------------------------------------------
+status:  solved
+timings: total: 3.02e-04s = setup: 4.97e-05s + solve: 2.53e-04s
+	 lin-sys: 1.68e-05s, cones: 1.29e-04s, accel: 3.09e-06s
+------------------------------------------------------------------
+objective = -0.000001
+------------------------------------------------------------------

As we can see in the log, SCS reports 6 variables and 11 constraints. We can also choose to dualize the problem before it is passed to SCS as follows:

using Dualization
+model_dual_scs = Model(dual_optimizer(SCS.Optimizer))
+@objective(model_dual_scs, Max, 0.0)
+con_ref = @constraint(model_dual_scs, p in SOSCone())
+optimize!(model_dual_scs)
------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 5, constraints m: 6
+cones: 	  s: psd vars: 6, ssize: 1
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 6, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 1.97e+02  1.05e+01  4.39e+03 -2.20e+03  1.00e-01  1.59e-04
+    50| 6.29e-06  1.81e-06  2.22e-05 -1.11e-05  1.00e-01  3.07e-04
+------------------------------------------------------------------
+status:  solved
+timings: total: 3.08e-04s = setup: 4.73e-05s + solve: 2.61e-04s
+	 lin-sys: 1.38e-05s, cones: 1.28e-04s, accel: 3.14e-06s
+------------------------------------------------------------------
+objective = -0.000011
+------------------------------------------------------------------

This time, SCS reports 5 variables and 6 constraints.

Bridges operating behind the scenes

The difference comes from the fact that, when designing the JuMP interface of SCS, it was decided that the model would be read in the image form. SCS therefore declares that it only supports free variables, represented in JuMP as variables in MOI.Reals and affine semidefinite constraints, represented in JuMP as MOI.VectorAffineFunction-in-MOI.PositiveSemidefiniteConeTriangle constraints. On the other hand, SumOfSquares gave the model in kernel form so the positive semidefinite (PSD) variables were reformulated as free variables constrained to be PSD using an affine PSD constraints.

This transformation is done transparently without warning but it can be inspected using print_active_bridges. As shown below, we can see Unsupported variable: MOI.PositiveSemidefiniteConeTriangle and adding as constraint indicating that PSD variables are not supported and they are added as free variables. Then we have Unsupported constraint: MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle indicating that SCS does not support constraining variables in the PSD cone so it will just convert it into affine expressions in the PSD cone. Of course, this is equivalent but it means that SCS will not exploit this particular structure of the problem hence solving might be less efficient.

print_active_bridges(model_scs)
 * Supported objective: MOI.ScalarAffineFunction{Float64}
+ * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-SumOfSquares.SOSPolynomialSet{FullSpace, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}}
+ |  bridged by:
+ |   SumOfSquares.Bridges.Constraint.SOSPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, FullSpace, Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}, Vector{Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}}}}, Union{SumOfSquares.EmptyCone, SumOfSquares.PositiveSemidefinite2x2ConeTriangle, MOI.Nonnegatives, MOI.PositiveSemidefiniteConeTriangle}, MOI.PositiveSemidefiniteConeTriangle, MonomialBasis, MonomialBasis, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}
+ |  may introduce:
+ |   * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-PolyJuMP.ZeroPolynomialSet{FullSpace, MonomialBasis, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}
+ |   |  bridged by:
+ |   |   PolyJuMP.Bridges.Constraint.ZeroPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}
+ |   |  may introduce:
+ |   |   * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Zeros
+ |   * Unsupported variable: SumOfSquares.EmptyCone
+ |   |  adding as constraint:
+ |   |   * Supported variable: MOI.Reals
+ |   |   * Unsupported constraint: MOI.VectorOfVariables-in-SumOfSquares.EmptyCone
+ |   |   |  bridged by:
+ |   |   |   SumOfSquares.Bridges.Constraint.EmptyBridge{Float64, MOI.VectorOfVariables}
+ |   |   |  may introduce:
+ |   * Unsupported variable: MOI.Nonnegatives
+ |   |  adding as constraint:
+ |   |   * Supported variable: MOI.Reals
+ |   |   * Unsupported constraint: MOI.VectorOfVariables-in-MOI.Nonnegatives
+ |   |   |  bridged by:
+ |   |   |   MOIB.Constraint.FunctionConversionBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables, MOI.Nonnegatives}
+ |   |   |  may introduce:
+ |   |   |   * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Nonnegatives
+ |   * Unsupported variable: SumOfSquares.PositiveSemidefinite2x2ConeTriangle
+ |   |  bridged by:
+ |   |    SumOfSquares.Bridges.Variable.PositiveSemidefinite2x2Bridge{Float64}
+ |   |  may introduce:
+ |   |   * Unsupported variable: MOI.RotatedSecondOrderCone
+ |   |   |  adding as constraint:
+ |   |   |   * Supported variable: MOI.Reals
+ |   |   |   * Unsupported constraint: MOI.VectorOfVariables-in-MOI.RotatedSecondOrderCone
+ |   |   |   |  bridged by:
+ |   |   |   |   MOIB.Constraint.RSOCtoSOCBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}
+ |   |   |   |  may introduce:
+ |   |   |   |   * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.SecondOrderCone
+ |   * Unsupported variable: MOI.PositiveSemidefiniteConeTriangle
+ |   |  adding as constraint:
+ |   |   * Supported variable: MOI.Reals
+ |   |   * Unsupported constraint: MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle
+ |   |   |  bridged by:
+ |   |   |   MOIB.Constraint.SetDotScalingBridge{Float64, MOI.PositiveSemidefiniteConeTriangle, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}
+ |   |   |  may introduce:
+ |   |   |   * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}
+ |   |   |   |  bridged by:
+ |   |   |   |   SCS.ScaledPSDConeBridge{Float64, MOI.VectorAffineFunction{Float64}}
+ |   |   |   |  may introduce:
+ |   |   |   |   * Supported constraint: MOI.VectorAffineFunction{Float64}-in-SCS.ScaledPSDCone

With the dual version, we can see that variables in the PSD cone are supported directly hence we don't need that extra conversion.

print_active_bridges(model_dual_scs)
 * Supported objective: MOI.ScalarAffineFunction{Float64}
+ * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-SumOfSquares.SOSPolynomialSet{FullSpace, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}}
+ |  bridged by:
+ |   SumOfSquares.Bridges.Constraint.SOSPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, FullSpace, Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}, Vector{Union{MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.Nonnegatives}, MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.EmptyCone}, MOI.ConstraintIndex{MOI.VectorOfVariables, SumOfSquares.PositiveSemidefinite2x2ConeTriangle}}}}, Union{SumOfSquares.EmptyCone, SumOfSquares.PositiveSemidefinite2x2ConeTriangle, MOI.Nonnegatives, MOI.PositiveSemidefiniteConeTriangle}, MOI.PositiveSemidefiniteConeTriangle, MonomialBasis, MonomialBasis, SumOfSquares.Certificate.Newton{SOSCone, MonomialBasis, SumOfSquares.Certificate.NewtonFilter{SumOfSquares.Certificate.NewtonDegreeBounds{Tuple{}}}}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}
+ |  may introduce:
+ |   * Unsupported constraint: MOI.VectorAffineFunction{Float64}-in-PolyJuMP.ZeroPolynomialSet{FullSpace, MonomialBasis, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}
+ |   |  bridged by:
+ |   |   PolyJuMP.Bridges.Constraint.ZeroPolynomialBridge{Float64, MOI.VectorAffineFunction{Float64}, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}
+ |   |  may introduce:
+ |   |   * Supported constraint: MOI.VectorAffineFunction{Float64}-in-MOI.Zeros
+ |   * Unsupported variable: SumOfSquares.EmptyCone
+ |   |  adding as constraint:
+ |   |   * Supported variable: MOI.Reals
+ |   |   * Unsupported constraint: MOI.VectorOfVariables-in-SumOfSquares.EmptyCone
+ |   |   |  bridged by:
+ |   |   |   SumOfSquares.Bridges.Constraint.EmptyBridge{Float64, MOI.VectorOfVariables}
+ |   |   |  may introduce:
+ |   * Supported variable: MOI.Nonnegatives
+ |   * Unsupported variable: SumOfSquares.PositiveSemidefinite2x2ConeTriangle
+ |   |  bridged by:
+ |   |    SumOfSquares.Bridges.Variable.PositiveSemidefinite2x2Bridge{Float64}
+ |   |  may introduce:
+ |   |   * Supported variable: MOI.RotatedSecondOrderCone
+ |   * Supported variable: MOI.PositiveSemidefiniteConeTriangle

In more details

Consider a polynomial

\[p(x) = \sum_{\alpha} p_\alpha x^\alpha,\]

a vector of monomials b(x) and the set

\[\mathcal{A}_\alpha = \{\,(\beta, \gamma) \in b(x)^2 \mid x^\beta x^\gamma = x^\alpha\,\}\]

The constraint encoding the existence of a PSD matrix Q such that p(x) = b(x)' * Q * b(x) can be written in standard conic form as follows:

\[\begin{aligned} + \langle \sum_{(\beta, \gamma) \in \mathcal{A}_\alpha} e_\beta e_\gamma^\top, Q \rangle & = p_\alpha, \quad\forall \alpha\\ + Q & \succeq 0 +\end{aligned}\]

Given an arbitrary choice of elements in each set $\mathcal{A}_\alpha$: $(\beta_\alpha, \gamma_\alpha) \in \mathcal{A}_\alpha$. It can also equivalently be written in the geometric conic form as follows:

\[\begin{aligned} + p_\alpha e_{\beta_\alpha} e_{\gamma_\alpha}^\top + + \sum_{(\beta, \gamma) \in \mathcal{A}_\alpha \setminus (\beta_\alpha, \gamma_\alpha)} + y_{\beta,\gamma} (e_\beta e_\gamma - e_{\beta_\alpha} e_{\gamma_\alpha}^\top)^\top + & \succeq 0\\ + y_{\beta,\gamma} & \text{ free} +\end{aligned}\]

Should I dualize or not ?

Let's study the evolution of the dimensions m and n of the semidefinite program in two extreme examples and then try to extrapolate from these.

Univariate case

Suppose p is a univariate polynomial of degree $2d$. Then n will be equal to d(d + 1)/2 for both the standard and geometric conic forms. On the other hand, m will be equal to 2d + 1 for the standard conic form and d(d + 1) / 2 - (2d + 1) for the geometric form case. So m grows linearly for the kernel form but quadratically for the image form!

Quadratic case

Suppose p is a quadratic form of d variables. Then n will be equal to d for both the standard and geometric conic forms. On the other hand, m will be equal to d(d + 1)/2 for the standard conic form and 0 for the geometric form case. So m grows quadratically for the kernel form but is zero for the image form!

In general

In general, if $s_d$ is the dimension of the space of polynomials of degree d then $m = s_{2d}$ for the kernel form and $m = s_{d}(s_{d} + 1)/2 - s_{2d}$ for the image form. As a rule of thumb, the kernel form will have a smaller m if p has a low number of variables and low degree and vice versa. Of course, you can always try with and without Dualization and see which one works best.


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/getting_started.ipynb b/previews/PR347/generated/Getting started/getting_started.ipynb new file mode 100644 index 000000000..57552edd7 --- /dev/null +++ b/previews/PR347/generated/Getting started/getting_started.ipynb @@ -0,0 +1,232 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Getting started" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: SOSTOOLS' SOSDEMO1 (See Section 4.1 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf)) and Example 2.4 of [PJ08]\n", + "\n", + "P. Parrilo and A. Jadbabaie\n", + "*Approximation of the joint spectral radius using sum of squares*.\n", + "Linear Algebra and its Applications, Elsevier (2008), 428, 2385-2402" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "5y⁴ - x²y² + 2x³y + 2x⁴", + "text/latex": "$$ 5y^{4} - x^{2}y^{2} + 2x^{3}y + 2x^{4} $$" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x y\n", + "p = 2*x^4 + 2*x^3*y - x^2*y^2 + 5*y^4" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "import CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = SOSModel(solver)\n", + "con_ref = @constraint(model, p >= 0)\n", + "optimize!(model)\n", + "primal_status(model)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We see above that the solver found a feasible solution.\n", + "We now inspect this solution:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "GramMatrix with row/column basis:\n MonomialBasis([y^2, x*y, x^2])\nAnd entries in a 3×3 SymMatrix{Float64}:\n 5.0 4.4408920985006264e-17 -2.9518518518518517\n 4.4408920985006264e-17 4.903703703703703 1.0\n -2.9518518518518517 1.0 2.0" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "q = gram_matrix(con_ref)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We can get the SOS decomposition from the gram matrix as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-2.1236350925148186*y^2 + 0.6856027338723613*x*y + 1.4043287476933908*x^2)^2 + (-0.6931517747987983*y^2 - 2.105348694339436*x*y - 0.020343251432300993*x^2)^2 + (0.09856272587979271*y^2 - 0.034050994900062574*x*y + 0.16567112157245342*x^2)^2" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "sosdec = SOSDecomposition(q)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We now seek for the SOS decomposition of the following polynomial:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "y² + x² - xy² + 4x⁴y⁶", + "text/latex": "$$ y^{2} + x^{2} - xy^{2} + 4x^{4}y^{6} $$" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "p = 4*x^4*y^6 + x^2 - x*y^2 + y^2" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We build the same model as previously with this new polynomial.\n", + "Here we can use `Model` instead of `SOSModel` as we explicitly constrain\n", + "`p` to belong to the SOS cone with `p in SOSCone()`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "model = Model(solver)\n", + "con_ref = @constraint(model, p in SOSCone())\n", + "optimize!(model)\n", + "primal_status(model)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We can query the SOS decomposition directly from the constraint reference\n", + "as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-0.8633544111907671*y + 0.1929775871076749*x*y + 2.8118914006146728e-18*x*y^2 + 1.9748040632461146*x^2*y^3)^2 + (-1.0044005280851495e-16*y + 0.7962855107812749*x - 3.604670114761173e-17*x*y - 1.7452642425911866*x*y^2 - 5.2795306922881863e-17*x^2*y^3)^2 + (0.24383463418983628*y - 1.7639164207923265e-16*x - 1.548639212897575*x*y + 3.447822046557963e-17*x*y^2 + 0.25793362243589024*x^2*y^3)^2 + (-5.040390840687567e-17*y + 0.604920974441955*x + 4.554029379037467e-17*x*y + 0.27599821010522485*x*y^2 - 4.6874560662018034e-17*x^2*y^3)^2 + (-0.4417735074073058*y - 5.425371220674707e-17*x - 0.10009637589813167*x*y + 1.353482119225013e-17*x*y^2 - 0.18335527863613874*x^2*y^3)^2" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "sos_decomposition(con_ref)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/getting_started.jl b/previews/PR347/generated/Getting started/getting_started.jl new file mode 100644 index 000000000..718382149 --- /dev/null +++ b/previews/PR347/generated/Getting started/getting_started.jl @@ -0,0 +1,26 @@ +using DynamicPolynomials +@polyvar x y +p = 2*x^4 + 2*x^3*y - x^2*y^2 + 5*y^4 + +using SumOfSquares +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver) +con_ref = @constraint(model, p >= 0) +optimize!(model) +primal_status(model) + +q = gram_matrix(con_ref) + +sosdec = SOSDecomposition(q) + +p = 4*x^4*y^6 + x^2 - x*y^2 + y^2 + +model = Model(solver) +con_ref = @constraint(model, p in SOSCone()) +optimize!(model) +primal_status(model) + +sos_decomposition(con_ref) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/getting_started/index.html b/previews/PR347/generated/Getting started/getting_started/index.html new file mode 100644 index 000000000..6fc3fc618 --- /dev/null +++ b/previews/PR347/generated/Getting started/getting_started/index.html @@ -0,0 +1,18 @@ + +Getting started · SumOfSquares

Getting started

Adapted from: SOSTOOLS' SOSDEMO1 (See Section 4.1 of SOSTOOLS User's Manual) and Example 2.4 of [PJ08]

P. Parrilo and A. Jadbabaie Approximation of the joint spectral radius using sum of squares. Linear Algebra and its Applications, Elsevier (2008), 428, 2385-2402

using DynamicPolynomials
+@polyvar x y
+p = 2*x^4 + 2*x^3*y - x^2*y^2 + 5*y^4

\[ 5y^{4} - x^{2}y^{2} + 2x^{3}y + 2x^{4} \]

We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.

using SumOfSquares
+import CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = SOSModel(solver)
+con_ref = @constraint(model, p >= 0)
+optimize!(model)
+primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

We see above that the solver found a feasible solution. We now inspect this solution:

q = gram_matrix(con_ref)
GramMatrix with row/column basis:
+ MonomialBasis([y^2, x*y, x^2])
+And entries in a 3×3 SymMatrix{Float64}:
+  5.0                     4.4408920985006264e-17  -2.9518518518518517
+  4.4408920985006264e-17  4.903703703703703        1.0
+ -2.9518518518518517      1.0                      2.0

We can get the SOS decomposition from the gram matrix as follows:

sosdec = SOSDecomposition(q)
(-2.1236350925148186*y^2 + 0.6856027338723613*x*y + 1.4043287476933908*x^2)^2 + (-0.6931517747987983*y^2 - 2.105348694339436*x*y - 0.020343251432300993*x^2)^2 + (0.09856272587979271*y^2 - 0.034050994900062574*x*y + 0.16567112157245342*x^2)^2

We now seek for the SOS decomposition of the following polynomial:

p = 4*x^4*y^6 + x^2 - x*y^2 + y^2

\[ y^{2} + x^{2} - xy^{2} + 4x^{4}y^{6} \]

We build the same model as previously with this new polynomial. Here we can use Model instead of SOSModel as we explicitly constrain p to belong to the SOS cone with p in SOSCone().

model = Model(solver)
+con_ref = @constraint(model, p in SOSCone())
+optimize!(model)
+primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

We can query the SOS decomposition directly from the constraint reference as follows:

sos_decomposition(con_ref)
(-0.8633544111907671*y + 0.1929775871076749*x*y + 2.8118914006146728e-18*x*y^2 + 1.9748040632461146*x^2*y^3)^2 + (-1.0044005280851495e-16*y + 0.7962855107812749*x - 3.604670114761173e-17*x*y - 1.7452642425911866*x*y^2 - 5.2795306922881863e-17*x^2*y^3)^2 + (0.24383463418983628*y - 1.7639164207923265e-16*x - 1.548639212897575*x*y + 3.447822046557963e-17*x*y^2 + 0.25793362243589024*x^2*y^3)^2 + (-5.040390840687567e-17*y + 0.604920974441955*x + 4.554029379037467e-17*x*y + 0.27599821010522485*x*y^2 - 4.6874560662018034e-17*x^2*y^3)^2 + (-0.4417735074073058*y - 5.425371220674707e-17*x - 0.10009637589813167*x*y + 1.353482119225013e-17*x*y^2 - 0.18335527863613874*x^2*y^3)^2

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/motzkin.ipynb b/previews/PR347/generated/Getting started/motzkin.ipynb new file mode 100644 index 000000000..41aba22f4 --- /dev/null +++ b/previews/PR347/generated/Getting started/motzkin.ipynb @@ -0,0 +1,6283 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Motzkin" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: (3.6) and (3.19) of [BPT12]\n", + "\n", + "[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R.\n", + "*Semidefinite Optimization and Convex Algebraic Geometry*.\n", + "Society for Industrial and Applied Mathematics, **2012**." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The first explicit example of nonnegative polynomial that is not a sum of squares was found by Motzkin in 1967. By the [Arithmetic-geometric mean](https://en.wikipedia.org/wiki/Arithmetic%E2%80%93geometric_mean),\n", + "$$ \\frac{x^4y^2 + x^2y^4 + 1}{3} \\ge \\sqrt[3]{x^4y^2 \\cdot x^2y^4 \\cdot 1} = x^2y^2 $$\n", + "hence\n", + "$$ x^4y^2 + x^2y^4 + 1 - 3x^2y^2 \\ge 0. $$\n", + "The code belows construct the Motzkin polynomial using [DynamicPolynomials](https://github.com/JuliaAlgebra/DynamicPolynomials.jl)." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1 - 3x²y² + x²y⁴ + x⁴y²", + "text/latex": "$$ 1 - 3x^{2}y^{2} + x^{2}y^{4} + x^{4}y^{2} $$" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x y\n", + "motzkin = x^4*y^2 + x^2*y^4 + 1 - 3x^2*y^2" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "The Motzkin polynomial is nonnegative but is not a sum of squares as we can verify numerically as follows.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "import CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = SOSModel(solver)\n", + "@constraint(model, motzkin >= 0) # We constraint `motzkin` to be a sum of squares\n", + "\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We see that the problem is detected as infeasible..." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "INFEASIBLE::TerminationStatusCode = 2" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "termination_status(model)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "... and that the dual solution is a certificate of the infeasibility of the problem." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "INFEASIBILITY_CERTIFICATE::ResultStatusCode = 4" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "dual_status(model)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Even if the Motzkin polynomial is not a sum of squares, it can still be certified to be nonnegative using sums of squares.\n", + "Indeed a polynomial is certified to be nonnegative if it is equal to a fraction of sums of squares.\n", + "The Motzkin polynomial is equal to a fraction of sums of squares whose denominator is $x^2 + y^2$.\n", + "This can be verified numerically as follows:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "model = SOSModel(solver)\n", + "@constraint(model, (x^2 + y^2) * motzkin >= 0) # We constraint the `(x^2 + y^2) * motzkin` to be a sum of squares\n", + "\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Now the problem is declared feasible by the solver..." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "OPTIMAL::TerminationStatusCode = 1" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "termination_status(model)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "... and the primal solution is a feasible point, hence it is a certificate of nonnegativity of the Motzkin polynomial." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "primal_status(model)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "One may consider ourself lucky to have had the intuition that $x^2 + y^2$ would work as denominator.\n", + "In fact, the search for the denominator can be carried out in parallel to the search of the numerator.\n", + "In the example below, we search for a denominator with monomials of degrees from 0 to 2.\n", + "If none is found, we can increase the maximum degree 2 to 4, 6, 8, ...\n", + "This gives a hierarchy of programs to try in order to certify the nonnegativity of a polynomial by identifying it with a fraction of sum of squares polynomials.\n", + "In the case of the Motzkin polynomial we now that degree 2 is enough since $x^2 + y^2$ works." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "6-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n 1\n y\n x\n y²\n xy\n x²" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(solver)\n", + "X = monomials([x, y], 0:2)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "We create a quadratic polynomial that is not necessarily a sum of squares since this is implied by the next constraint: `deno >= 1`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1]) + (_[2])y + (_[3])x + (_[4])y² + (_[5])xy + (_[6])x²", + "text/latex": "$$ ({\\_}_{1}) + ({\\_}_{2})y + ({\\_}_{3})x + ({\\_}_{4})y^{2} + ({\\_}_{5})xy + ({\\_}_{6})x^{2} $$" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "@variable(model, deno, Poly(X))" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "We want the denominator polynomial to be strictly positive, this prevents the trivial solution deno = 0 for instance." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "@constraint(model, deno >= 1)\n", + "@constraint(model, deno * motzkin >= 0)\n", + "optimize!(model)\n", + "\n", + "termination_status(model)\n", + "\n", + "primal_status(model)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "We can check the denominator found by the program using `JuMP.value`" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "23.255419067239504 + 12.293357118019848y² + 12.293357283456736x²", + "text/latex": "$$ 23.255419067239504 + 12.293357118019848y^{2} + 12.293357283456736x^{2} $$" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "value(deno)" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "Because a picture is worth a thousand words let's plot the beast.\n", + "We can easily extend `Plots` by adding a recipe to plot bivariate polynomials." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=1}", + "image/png": "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1CUr6M2t5kp7pLmq8cNj8odcssYTnym8Td1KpdLg2t5qczAWQvaLThcshEyEtAins492NuLaCYBMXs1UIbTDjOCTxvhN2bLoHdNMHFzvb20Oxt5RhAPO42yZ6YEfbKYE+VzsrKxUKpQ5ue3474Yo4OIjlsdQBSuVCgAM3Ej1lL13rKAPnF0w8WMPsA8uAjYu+oI0E5eWlpaXl/P5fLValdX6q6ur/Th6XETP1fRTCf8RTjy33377S17ykh122KFQKLz3ve+VKx999NFDDz10jz322Lhx46c+9amOB2m1WisrK0L0PjHh4CgWi3Ia2IG/k6tbQboERiMNwQsQBYp2u7giGg0OVn/05oFf2iwRBMHi4mKhUFhcXGy1WsVisVgs1mq17A+FJnf8oxUgZCGcStg1Otls37798MMPP+2007Zt2yaEuPfee+X6973vfc961rO+973v3XnnnQcddNDLX/7yvffeO+0gcR/tMRPCYU/2ZM07Abark5K+TUx6TdEbOCS/f9WTa8P0k770/kahimIo9o7ylzZlsBBONhdccMHee+998skny5f77rsvAFSr1a9+9as//elPhRDPf/7zjzjiiAsuuOBDH/pQcvcwDH/3u98tLCzIDJSuJmMaNP3qo52R1R8eY89EaApiSqpn1npBHSOUaooA5BFRZpD03vvbTpCRNfXj82fC9AX+Pieb22+/fc899zz88MM3bdq0devWW2+9FQB+85vf1Ot1KYoAsN9++91///3JfRuNxuc+97mPfOQjOgNlfCxC2W2rP320M5LmC/V7O4P2jtOkHzV2n6LAhOu1+ZMTh3SZM4+393e5XE7r/Y2IyS6j7BqdMtginGweffTRq6+++pprrjnwwAPPPffco48++q677nrqqafMVo2FQuHJJ59M7nv33XfvvPPO5513nl4zJhahnNN148aNw8yoNFJGLdOtbdaoXSwYb0nM69vZduQUxBHQsff3veeJZPkgu0anjzG47TFrYJdddjnssMMOPvjgIAhOPfXUhx566J577tlll12q1Wqj0ZBjtm/fvmnTpuS+mzdvPvroo83wm7QIv3j4KP/KK5XKaCZ7ijNlkqZhB+PPNPXksi+htP1Bxq6V60whzcRCoSDNxHK5LJNOVYIMctbodMNCONk8//nP1wnirVYrDMNcLrf77rvvuOOOP/vZz+T6n/3s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", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "using RecipesBase\n", + "@recipe function f(x::AbstractVector, y::AbstractVector, p::Polynomial)\n", + " x, y, (x, y) -> p(variables(p) => [x, y])\n", + "end\n", + "import Plots\n", + "Plots.plot(\n", + " range(-2, stop=2, length=100),\n", + " range(-2, stop=2, length=100),\n", + " motzkin,\n", + " st = [:surface],\n", + " seriescolor=:heat,\n", + " colorbar=:none,\n", + " clims = (-10, 80)\n", + ")" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/motzkin.jl b/previews/PR347/generated/Getting started/motzkin.jl new file mode 100644 index 000000000..b14165f50 --- /dev/null +++ b/previews/PR347/generated/Getting started/motzkin.jl @@ -0,0 +1,56 @@ +using DynamicPolynomials +@polyvar x y +motzkin = x^4*y^2 + x^2*y^4 + 1 - 3x^2*y^2 + +using SumOfSquares +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver) +@constraint(model, motzkin >= 0) # We constraint `motzkin` to be a sum of squares + +optimize!(model) + +termination_status(model) + +dual_status(model) + +model = SOSModel(solver) +@constraint(model, (x^2 + y^2) * motzkin >= 0) # We constraint the `(x^2 + y^2) * motzkin` to be a sum of squares + +optimize!(model) + +termination_status(model) + +primal_status(model) + +model = SOSModel(solver) +X = monomials([x, y], 0:2) + +@variable(model, deno, Poly(X)) + +@constraint(model, deno >= 1) +@constraint(model, deno * motzkin >= 0) +optimize!(model) + +termination_status(model) + +primal_status(model) + +value(deno) + +using RecipesBase +@recipe function f(x::AbstractVector, y::AbstractVector, p::Polynomial) + x, y, (x, y) -> p(variables(p) => [x, y]) +end +import Plots +Plots.plot( + range(-2, stop=2, length=100), + range(-2, stop=2, length=100), + motzkin, + st = [:surface], + seriescolor=:heat, + colorbar=:none, + clims = (-10, 80) +) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/motzkin/dbb8d891.svg b/previews/PR347/generated/Getting started/motzkin/dbb8d891.svg new file mode 100644 index 000000000..80abdc36b --- /dev/null +++ b/previews/PR347/generated/Getting started/motzkin/dbb8d891.svg @@ -0,0 +1,2951 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Getting started/motzkin/index.html b/previews/PR347/generated/Getting started/motzkin/index.html new file mode 100644 index 000000000..4a4274914 --- /dev/null +++ b/previews/PR347/generated/Getting started/motzkin/index.html @@ -0,0 +1,39 @@ + +Motzkin · SumOfSquares

Motzkin

Adapted from: (3.6) and (3.19) of [BPT12]

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

The first explicit example of nonnegative polynomial that is not a sum of squares was found by Motzkin in 1967. By the Arithmetic-geometric mean, $ \frac{x^4y^2 + x^2y^4 + 1}{3} \ge \sqrt[3]{x^4y^2 \cdot x^2y^4 \cdot 1} = x^2y^2 $ hence $ x^4y^2 + x^2y^4 + 1 - 3x^2y^2 \ge 0. $ The code belows construct the Motzkin polynomial using DynamicPolynomials.

using DynamicPolynomials
+@polyvar x y
+motzkin = x^4*y^2 + x^2*y^4 + 1 - 3x^2*y^2

\[ 1 - 3x^{2}y^{2} + x^{2}y^{4} + x^{4}y^{2} \]

The Motzkin polynomial is nonnegative but is not a sum of squares as we can verify numerically as follows. We first need to pick an SDP solver, see here for a list of the available choices.

using SumOfSquares
+import CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = SOSModel(solver)
+@constraint(model, motzkin >= 0) # We constraint `motzkin` to be a sum of squares
+
+optimize!(model)

We see that the problem is detected as infeasible...

termination_status(model)
INFEASIBLE::TerminationStatusCode = 2

... and that the dual solution is a certificate of the infeasibility of the problem.

dual_status(model)
INFEASIBILITY_CERTIFICATE::ResultStatusCode = 4

Even if the Motzkin polynomial is not a sum of squares, it can still be certified to be nonnegative using sums of squares. Indeed a polynomial is certified to be nonnegative if it is equal to a fraction of sums of squares. The Motzkin polynomial is equal to a fraction of sums of squares whose denominator is $x^2 + y^2$. This can be verified numerically as follows:

model = SOSModel(solver)
+@constraint(model, (x^2 + y^2) * motzkin >= 0) # We constraint the `(x^2 + y^2) * motzkin` to be a sum of squares
+
+optimize!(model)

Now the problem is declared feasible by the solver...

termination_status(model)
OPTIMAL::TerminationStatusCode = 1

... and the primal solution is a feasible point, hence it is a certificate of nonnegativity of the Motzkin polynomial.

primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

One may consider ourself lucky to have had the intuition that $x^2 + y^2$ would work as denominator. In fact, the search for the denominator can be carried out in parallel to the search of the numerator. In the example below, we search for a denominator with monomials of degrees from 0 to 2. If none is found, we can increase the maximum degree 2 to 4, 6, 8, ... This gives a hierarchy of programs to try in order to certify the nonnegativity of a polynomial by identifying it with a fraction of sum of squares polynomials. In the case of the Motzkin polynomial we now that degree 2 is enough since $x^2 + y^2$ works.

model = SOSModel(solver)
+X = monomials([x, y], 0:2)
6-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ 1
+ y
+ x
+ y²
+ xy
+ x²

We create a quadratic polynomial that is not necessarily a sum of squares since this is implied by the next constraint: deno >= 1.

@variable(model, deno, Poly(X))

\[ ({\_}_{1}) + ({\_}_{2})y + ({\_}_{3})x + ({\_}_{4})y^{2} + ({\_}_{5})xy + ({\_}_{6})x^{2} \]

We want the denominator polynomial to be strictly positive, this prevents the trivial solution deno = 0 for instance.

@constraint(model, deno >= 1)
+@constraint(model, deno * motzkin >= 0)
+optimize!(model)
+
+termination_status(model)
+
+primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

We can check the denominator found by the program using JuMP.value

value(deno)

\[ 23.255419067239504 + 12.293357118019848y^{2} + 12.293357283456736x^{2} \]

Because a picture is worth a thousand words let's plot the beast. We can easily extend Plots by adding a recipe to plot bivariate polynomials.

using RecipesBase
+@recipe function f(x::AbstractVector, y::AbstractVector, p::Polynomial)
+    x, y, (x, y) -> p(variables(p) => [x, y])
+end
+import Plots
+Plots.plot(
+    range(-2, stop=2, length=100),
+    range(-2, stop=2, length=100),
+    motzkin,
+    st = [:surface],
+    seriescolor=:heat,
+    colorbar=:none,
+    clims = (-10, 80)
+)
Example block output

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/sos_decomposition.ipynb b/previews/PR347/generated/Getting started/sos_decomposition.ipynb new file mode 100644 index 000000000..25a329a16 --- /dev/null +++ b/previews/PR347/generated/Getting started/sos_decomposition.ipynb @@ -0,0 +1,281 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# A trivial SOS decomposition example" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: votroto\n", + "**Adapted from**: Examples 3.25 of [BPT12]\n", + "\n", + "[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R.\n", + "*Semidefinite Optimization and Convex Algebraic Geometry*.\n", + "Society for Industrial and Applied Mathematics, **2012**." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "using SumOfSquares\n", + "import CSDP" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "The polynomial `p = x^2 - x*y^2 + y^4 + 1` is SOS.\n", + "We can, for example, decompose it as\n", + "`p = 3/4*(x - y^2)^2 + 1/4*(x + y)^2 + 1`,\n", + "which clearly proves that `p` is SOS, and there are infinitely many other ways\n", + "to decompose `p` into sums of squares." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We can use SumOfSquares.jl to find such decompositions." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "First, setup the polynomial of interest." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1 + x² - xy² + y⁴", + "text/latex": "$$ 1 + x^{2} - xy^{2} + y^{4} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "@polyvar x y\n", + "p = x^2 - x*y^2 + y^4 + 1" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "Secondly, constrain the polynomial to be nonnegative.\n", + "SumOfSquares.jl transparently reinterprets polyonmial nonnegativity as the\n", + "appropriate SOS certificate for polynomials nonnegative on semialgebraic sets." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "cref : (1) + (1)x² + (-1)xy² + (1)y⁴ is SOS", + "text/latex": "$$ (1) + (1)x^{2} + (-1)xy^{2} + (1)y^{4} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(CSDP.Optimizer)\n", + "@constraint(model, cref, p >= 0)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Thirdly, optimize the feasibility problem!" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.00e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 2.7659722e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 1.2562719e+01 \n" + ] + } + ], + "cell_type": "code", + "source": [ + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Lastly, recover a SOS decomposition.\n", + "In general, SOS decompositions are not unique!" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-0.7423566403018642 - 0.5916342145954683*x + 0.9492757372229985*y^2)^2 + (-6.60921131771784e-17 + 1.1201589623631873*y - 2.4872525425116695e-16*x - 1.0534655002111817e-16*y^2)^2 + (0.6232480104529257 - 0.782024243528594*x + 5.551115123125783e-17*y^2)^2 + (-0.2459035096662894 - 1.2342687879752308e-17*y - 0.19597713808894587*x - 0.31444486753600015*y^2)^2" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "sos_dec = sos_decomposition(cref, 1e-4)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Converting, rounding, and simplifying - Huzza, Back where we began!" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1.0 - 1.4199712e-16y + 7.4940054e-16x - 5.551115e-16y² - 5.5238587e-16xy + x² - 2.2824759e-16y³ - xy² + y⁴", + "text/latex": "$$ 1.0 - 1.4199712 \\cdot 10^{-16}y + 7.4940054 \\cdot 10^{-16}x - 5.551115 \\cdot 10^{-16}y^{2} - 5.5238587 \\cdot 10^{-16}xy + x^{2} - 2.2824759 \\cdot 10^{-16}y^{3} - xy^{2} + y^{4} $$" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "polynomial(sos_dec, Float32)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "## A deeper explanation and the unexplained `1e-4` parameter" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "`p = x^2 - x*y^2 + y^4 + 1` can be represented in terms of its Gram matrix as" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "GramMatrix with row/column basis:\n MonomialBasis([1, y, x, y^2])\nAnd entries in a 4×4 SymMatrix{Float64}:\n 1.0 0.0 … -0.6273780504812863\n 0.0 1.2547561009625725 0.0\n 4.933553565678038e-17 0.0 -0.5\n -0.6273780504812863 0.0 1.0" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "gram = gram_matrix(cref)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1.0 + 9.867107131356075e-17x + x² - xy² + y⁴", + "text/latex": "$$ 1.0 + 9.867107131356075 \\cdot 10^{-17}x + x^{2} - xy^{2} + y^{4} $$" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "gram.basis.monomials' * gram.Q * gram.basis.monomials" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "where the matrix `gram.Q` is positive semidefinite, because `p` is SOS. If we\n", + "could only get the decomposition `gram.Q = V' * V`, the SOS decomposition would\n", + "simply be `||V * monomials||^2`." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Unfortunately, we can not use Cholesky decomposition, since gram `Q` is only\n", + "semidefinite, not definite. Hence, SumOfSquares.jl uses SVD decomposition\n", + "instead and discards small singular values (in our case `1e-4`)." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/sos_decomposition.jl b/previews/PR347/generated/Getting started/sos_decomposition.jl new file mode 100644 index 000000000..964b04db5 --- /dev/null +++ b/previews/PR347/generated/Getting started/sos_decomposition.jl @@ -0,0 +1,21 @@ +using DynamicPolynomials +using SumOfSquares +import CSDP + +@polyvar x y +p = x^2 - x*y^2 + y^4 + 1 + +model = SOSModel(CSDP.Optimizer) +@constraint(model, cref, p >= 0) + +optimize!(model) + +sos_dec = sos_decomposition(cref, 1e-4) + +polynomial(sos_dec, Float32) + +gram = gram_matrix(cref) + +gram.basis.monomials' * gram.Q * gram.basis.monomials + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/sos_decomposition/index.html b/previews/PR347/generated/Getting started/sos_decomposition/index.html new file mode 100644 index 000000000..70d56ee78 --- /dev/null +++ b/previews/PR347/generated/Getting started/sos_decomposition/index.html @@ -0,0 +1,16 @@ + +A trivial SOS decomposition example · SumOfSquares

A trivial SOS decomposition example

Contributed by: votroto Adapted from: Examples 3.25 of [BPT12]

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

using DynamicPolynomials
+using SumOfSquares
+import CSDP

The polynomial p = x^2 - x*y^2 + y^4 + 1 is SOS. We can, for example, decompose it as p = 3/4*(x - y^2)^2 + 1/4*(x + y)^2 + 1, which clearly proves that p is SOS, and there are infinitely many other ways to decompose p into sums of squares.

We can use SumOfSquares.jl to find such decompositions.

First, setup the polynomial of interest.

@polyvar x y
+p = x^2 - x*y^2 + y^4 + 1

\[ 1 + x^{2} - xy^{2} + y^{4} \]

Secondly, constrain the polynomial to be nonnegative. SumOfSquares.jl transparently reinterprets polyonmial nonnegativity as the appropriate SOS certificate for polynomials nonnegative on semialgebraic sets.

model = SOSModel(CSDP.Optimizer)
+@constraint(model, cref, p >= 0)

\[ (1) + (1)x^{2} + (-1)xy^{2} + (1)y^{4} \text{ is SOS} \]

Thirdly, optimize the feasibility problem!

optimize!(model)
CSDP 6.2.0
+This is a pure primal feasibility problem.
+Iter:  0 Ap: 0.00e+00 Pobj:  0.0000000e+00 Ad: 0.00e+00 Dobj:  0.0000000e+00
+Iter:  1 Ap: 9.00e-01 Pobj:  0.0000000e+00 Ad: 1.00e+00 Dobj:  2.7659722e+01
+Iter:  2 Ap: 1.00e+00 Pobj:  0.0000000e+00 Ad: 1.00e+00 Dobj:  1.2562719e+01

Lastly, recover a SOS decomposition. In general, SOS decompositions are not unique!

sos_dec = sos_decomposition(cref, 1e-4)
(-0.7423566403018642 - 0.5916342145954683*x + 0.9492757372229985*y^2)^2 + (-6.60921131771784e-17 + 1.1201589623631873*y - 2.4872525425116695e-16*x - 1.0534655002111817e-16*y^2)^2 + (0.6232480104529257 - 0.782024243528594*x + 5.551115123125783e-17*y^2)^2 + (-0.2459035096662894 - 1.2342687879752308e-17*y - 0.19597713808894587*x - 0.31444486753600015*y^2)^2

Converting, rounding, and simplifying - Huzza, Back where we began!

polynomial(sos_dec, Float32)

\[ 1.0 - 1.4199712 \cdot 10^{-16}y + 7.4940054 \cdot 10^{-16}x - 5.551115 \cdot 10^{-16}y^{2} - 5.5238587 \cdot 10^{-16}xy + x^{2} - 2.2824759 \cdot 10^{-16}y^{3} - xy^{2} + y^{4} \]

A deeper explanation and the unexplained 1e-4 parameter

p = x^2 - x*y^2 + y^4 + 1 can be represented in terms of its Gram matrix as

gram = gram_matrix(cref)
GramMatrix with row/column basis:
+ MonomialBasis([1, y, x, y^2])
+And entries in a 4×4 SymMatrix{Float64}:
+  1.0                    0.0                 …  -0.6273780504812863
+  0.0                    1.2547561009625725      0.0
+  4.933553565678038e-17  0.0                    -0.5
+ -0.6273780504812863     0.0                     1.0
gram.basis.monomials' * gram.Q * gram.basis.monomials

\[ 1.0 + 9.867107131356075 \cdot 10^{-17}x + x^{2} - xy^{2} + y^{4} \]

where the matrix gram.Q is positive semidefinite, because p is SOS. If we could only get the decomposition gram.Q = V' * V, the SOS decomposition would simply be ||V * monomials||^2.

Unfortunately, we can not use Cholesky decomposition, since gram Q is only semidefinite, not definite. Hence, SumOfSquares.jl uses SVD decomposition instead and discards small singular values (in our case 1e-4).


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/sum-of-squares_matrices.ipynb b/previews/PR347/generated/Getting started/sum-of-squares_matrices.ipynb new file mode 100644 index 000000000..15bff92d4 --- /dev/null +++ b/previews/PR347/generated/Getting started/sum-of-squares_matrices.ipynb @@ -0,0 +1,312 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Sum-of-Squares matrices" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Examples 3.77 of [BPT12]\n", + "\n", + "[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R.\n", + "*Semidefinite Optimization and Convex Algebraic Geometry*.\n", + "Society for Industrial and Applied Mathematics, **2012**." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the symmetric polynomial matrix\n", + "$$P(x) =\n", + "\\begin{bmatrix}\n", + " x^2 - 2x + 2 & x\\\\\n", + " x & x^2\n", + "\\end{bmatrix}.$$\n", + "We could like to know whether $P(x)$ is positive semidefinite for all $x \\in \\mathbb{R}$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2×2 Matrix{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Int64}}:\n 2 - 2x + x² x\n x x²" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x\n", + "P = [x^2 - 2x + 2 x\n", + " x x^2]" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "A sufficient condition for a symmetric polynomial matrix $P(x)$ to be positive semidefinite for all $x$ is to the existence of a matrix $M(x)$ such that $P(x) = M^\\top(x) M(x)$. If such matrix $M$ exists, we say that the matrix is an \\emph{sos matrix} (see [Definition 3.76, BPT13]).\n", + "While determining whether $P(x)$ is positive semidefinite for all $x$, is NP-hard (checking nonnegativity of a polynomial is reduced to this problem for $1 \\times 1$ matrices), checking whether $P(x)$ is an sos matrix is an sos program." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "OPTIMAL::TerminationStatusCode = 1" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "\n", + "model = SOSModel(solver)\n", + "mat_cref = @constraint(model, P in PSDCone())\n", + "optimize!(model)\n", + "termination_status(model)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "While the reformulation of sos matrix to sos polynomial is rather simple, as explained in the \"Sum-of-Squares reformulation\" section below, there is a technical subtelty about the Newton polytope that if not handled correctly may result in an SDP of large size with bad numerical behavior. For this reason, it is recommended to model sos *matrix* constraints as such as will be shown in this notebook and not do the formulation manually unless there is a specific reason to do so.\n", + "\n", + "As we can verify as follows, only 3 monomials are used using the sos *matrix* constraint." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n ##287\n x##289\n x##287" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "certificate_monomials(mat_cref)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "### Sum-of-Squares reformulation\n", + "\n", + "One way to obtain the reduction to an sos program is to create an intermediate vector of variable $y$ and check whether the polynomial $p(x, y) = y^\\top P(x) y$ is sos.\n", + "However, special care is required when approximating the Newton polytope of $p(x, y)$.\n", + "Indeed, for instance if the entries of $P(x)$ are quadratic forms then the Newton polytope of $p(x, y)$ is the cartesian product between the Newton polytope of $y^\\top y$ and the Newton polytope of $x^\\top x$.\n", + "In other words, $p(x, y)$ belongs to a family of quartic forms called biquadratic forms.\n", + "This fact is important when generating the semidefinite program so that only bilinear monomials are used.\n", + "So if the cheap outer approximation is used (instead of the exact polyhedral computation) for the newton polytope then it is important to use a multipartite computation approximation of the newton polytope.\n", + "The multipartie exact approach may perform worse compared to the unipartite exact in certain cases though.\n", + "Consider for instance the polynomial matrix $\\mathrm{Diag}(x_1^1, x_2^2)$ for which $p(x, y) = x_1^2y_1^2 + x_2^2y_2^2$.\n", + "For this polynomial, only the monomials $x_1y_1$ and $x_2y_2$ are needed in the SDP reformulation while the multipartite approach,\n", + "as it will compute the Newton polytope as a cartesian product, will not see the dependence between $x$ and $y$ in the presence of monomials and will also select the monomials $x_1y_2$ and $x_2y_1$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2y₁² + 2xy₁y₂ - 2xy₁² + x²y₂² + x²y₁²", + "text/latex": "$$ 2y_{1}^{2} + 2xy_{1}y_{2} - 2xy_{1}^{2} + x^{2}y_{2}^{2} + x^{2}y_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "@polyvar y[1:2]\n", + "p = vec(y)' * P * vec(y)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We can see above that `p` is biquadratic polynomial in the variables `x` and `y`.\n", + "Computing the Newton polytope with the cheap outer approximation\n", + "without exploiting this multipartite structure gives the following 6 monomials." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "6-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n y₂\n y₁\n x\n y₁y₂\n xy₂\n xy₁" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "X = monomials(p)\n", + "unipartite = Certificate.NewtonDegreeBounds(tuple())\n", + "Certificate.monomials_half_newton_polytope(X, unipartite)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "Exploiting the multipartite structure gives 4 monomials." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "4-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n y₂\n y₁\n xy₂\n xy₁" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "multipartite = Certificate.NewtonDegreeBounds(([x], y))\n", + "Certificate.monomials_half_newton_polytope(X, multipartite)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "In the example above, there were only 3 monomials, where does the difference come from ?\n", + "Using the monomial basis, the only product of two monomials that is equal to\n", + "`y[2]^2` is `y[2] * y[2]`. As `y[2]^2` is not a monomial of `p`, we can conclude\n", + "that the diagonal entry with row and column corresponding to `y[2]` will be zero\n", + "hence the whole column and row will be zero as well.\n", + "Therefore, we can remove this monomial." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n y₁\n xy₂\n xy₁" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(multipartite))" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "The same reasoning can be used for monomials `y[1]y[2]` and `x` therefore whether\n", + "we exploit the multipartite structure or not, we get only 3 monomials thanks\n", + "to this post filter." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n y₁\n xy₂\n xy₁" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(unipartite))" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/sum-of-squares_matrices.jl b/previews/PR347/generated/Getting started/sum-of-squares_matrices.jl new file mode 100644 index 000000000..6c9af62cd --- /dev/null +++ b/previews/PR347/generated/Getting started/sum-of-squares_matrices.jl @@ -0,0 +1,24 @@ +using DynamicPolynomials +@polyvar x +P = [x^2 - 2x + 2 x + x x^2] + +using SumOfSquares + +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + +model = SOSModel(solver) +mat_cref = @constraint(model, P in PSDCone()) +optimize!(model) +termination_status(model) + +@polyvar y[1:2] +p = vec(y)' * P * vec(y) + +X = monomials(p) +unipartite = Certificate.NewtonDegreeBounds(tuple()) + +multipartite = Certificate.NewtonDegreeBounds(([x], y)) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/sum-of-squares_matrices/index.html b/previews/PR347/generated/Getting started/sum-of-squares_matrices/index.html new file mode 100644 index 000000000..3dc2e74dd --- /dev/null +++ b/previews/PR347/generated/Getting started/sum-of-squares_matrices/index.html @@ -0,0 +1,37 @@ + +Sum-of-Squares matrices · SumOfSquares

Sum-of-Squares matrices

Adapted from: Examples 3.77 of [BPT12]

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

Introduction

Consider the symmetric polynomial matrix $P(x) = \begin{bmatrix} x^2 - 2x + 2 & x\\ + x & x^2 \end{bmatrix}.$ We could like to know whether $P(x)$ is positive semidefinite for all $x \in \mathbb{R}$.

using DynamicPolynomials
+@polyvar x
+P = [x^2 - 2x + 2 x
+            x     x^2]
2×2 Matrix{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Int64}}:
+ 2 - 2x + x²  x
+ x            x²

A sufficient condition for a symmetric polynomial matrix $P(x)$ to be positive semidefinite for all $x$ is to the existence of a matrix $M(x)$ such that $P(x) = M^\top(x) M(x)$. If such matrix $M$ exists, we say that the matrix is an \emph{sos matrix} (see [Definition 3.76, BPT13]). While determining whether $P(x)$ is positive semidefinite for all $x$, is NP-hard (checking nonnegativity of a polynomial is reduced to this problem for $1 \times 1$ matrices), checking whether $P(x)$ is an sos matrix is an sos program.

using SumOfSquares

We first need to pick an SDP solver, see here for a list of the available choices.

import CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+
+model = SOSModel(solver)
+mat_cref = @constraint(model, P in PSDCone())
+optimize!(model)
+termination_status(model)
OPTIMAL::TerminationStatusCode = 1

While the reformulation of sos matrix to sos polynomial is rather simple, as explained in the "Sum-of-Squares reformulation" section below, there is a technical subtelty about the Newton polytope that if not handled correctly may result in an SDP of large size with bad numerical behavior. For this reason, it is recommended to model sos matrix constraints as such as will be shown in this notebook and not do the formulation manually unless there is a specific reason to do so.

As we can verify as follows, only 3 monomials are used using the sos matrix constraint.

certificate_monomials(mat_cref)
3-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ ##45274
+ x##45276
+ x##45274

Sum-of-Squares reformulation

One way to obtain the reduction to an sos program is to create an intermediate vector of variable $y$ and check whether the polynomial $p(x, y) = y^\top P(x) y$ is sos. However, special care is required when approximating the Newton polytope of $p(x, y)$. Indeed, for instance if the entries of $P(x)$ are quadratic forms then the Newton polytope of $p(x, y)$ is the cartesian product between the Newton polytope of $y^\top y$ and the Newton polytope of $x^\top x$. In other words, $p(x, y)$ belongs to a family of quartic forms called biquadratic forms. This fact is important when generating the semidefinite program so that only bilinear monomials are used. So if the cheap outer approximation is used (instead of the exact polyhedral computation) for the newton polytope then it is important to use a multipartite computation approximation of the newton polytope. The multipartie exact approach may perform worse compared to the unipartite exact in certain cases though. Consider for instance the polynomial matrix $\mathrm{Diag}(x_1^1, x_2^2)$ for which $p(x, y) = x_1^2y_1^2 + x_2^2y_2^2$. For this polynomial, only the monomials $x_1y_1$ and $x_2y_2$ are needed in the SDP reformulation while the multipartite approach, as it will compute the Newton polytope as a cartesian product, will not see the dependence between $x$ and $y$ in the presence of monomials and will also select the monomials $x_1y_2$ and $x_2y_1$.

@polyvar y[1:2]
+p = vec(y)' * P * vec(y)

\[ 2y_{1}^{2} + 2xy_{1}y_{2} - 2xy_{1}^{2} + x^{2}y_{2}^{2} + x^{2}y_{1}^{2} \]

We can see above that p is biquadratic polynomial in the variables x and y. Computing the Newton polytope with the cheap outer approximation without exploiting this multipartite structure gives the following 6 monomials.

X = monomials(p)
+unipartite = Certificate.NewtonDegreeBounds(tuple())
+Certificate.monomials_half_newton_polytope(X, unipartite)
6-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ y₂
+ y₁
+ x
+ y₁y₂
+ xy₂
+ xy₁

Exploiting the multipartite structure gives 4 monomials.

multipartite = Certificate.NewtonDegreeBounds(([x], y))
+Certificate.monomials_half_newton_polytope(X, multipartite)
4-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ y₂
+ y₁
+ xy₂
+ xy₁

In the example above, there were only 3 monomials, where does the difference come from ? Using the monomial basis, the only product of two monomials that is equal to y[2]^2 is y[2] * y[2]. As y[2]^2 is not a monomial of p, we can conclude that the diagonal entry with row and column corresponding to y[2] will be zero hence the whole column and row will be zero as well. Therefore, we can remove this monomial.

Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(multipartite))
3-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ y₁
+ xy₂
+ xy₁

The same reasoning can be used for monomials y[1]y[2] and x therefore whether we exploit the multipartite structure or not, we get only 3 monomials thanks to this post filter.

Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(unipartite))
3-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ y₁
+ xy₂
+ xy₁

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Getting started/univariate.ipynb b/previews/PR347/generated/Getting started/univariate.ipynb new file mode 100644 index 000000000..e49c7e724 --- /dev/null +++ b/previews/PR347/generated/Getting started/univariate.ipynb @@ -0,0 +1,544 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Minimization of a univariate polynomial" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "using SumOfSquares\n", + "import CSDP" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "Consider the problem of finding both the minimum value of `p = x^4 - 4x^3 - 2x^2 + 12x + 3` as well as its minimizers." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We can use SumOfSquares.jl to find such these values as follows.\n", + "We first define the polynomial using DynamicPolynomials." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3 + 12x - 2x² - 4x³ + x⁴", + "text/latex": "$$ 3 + 12x - 2x^{2} - 4x^{3} + x^{4} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "@polyvar x\n", + "p = x^4 - 4x^3 - 2x^2 + 12x + 3" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "Secondly, we create a Sum-of-Squares program searching for the maximal lower bound `σ` of the polynomial." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "σ", + "text/latex": "$ σ $" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(CSDP.Optimizer)\n", + "@variable(model, σ)\n", + "@constraint(model, cref, p >= σ)\n", + "@objective(model, Max, σ)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Thirdly, solve the program and find `σ = -6` as lower bound:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: SDP solved\n", + "Primal objective value: 0.0000000e+00 \n", + "Dual objective value: 0.0000000e+00 \n", + "Relative primal infeasibility: 3.29e-17 \n", + "Relative dual infeasibility: 5.00e-11 \n", + "Real Relative Gap: 0.00e+00 \n", + "XZ Relative Gap: 1.06e-10 \n", + "DIMACS error measures: 4.93e-17 0.00e+00 5.00e-11 0.00e+00 0.00e+00 1.06e-10\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 8.10e-01 Pobj: -1.3830330e+01 Ad: 7.29e-01 Dobj: -8.2765454e+00 \n", + "Iter: 2 Ap: 9.00e-01 Pobj: -1.5490537e+01 Ad: 9.00e-01 Dobj: -1.3831579e-01 \n", + "Iter: 3 Ap: 1.00e+00 Pobj: -7.5281681e+00 Ad: 9.00e-01 Dobj: -3.8241528e+00 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -6.0076491e+00 Ad: 9.00e-01 Dobj: -5.7732642e+00 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -6.0000210e+00 Ad: 1.00e+00 Dobj: -5.9999957e+00 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -6.0000045e+00 Ad: 1.00e+00 Dobj: -6.0000015e+00 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -6.0000003e+00 Ad: 1.00e+00 Dobj: -6.0000001e+00 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : -6.00000e+00\n Dual objective value : -6.00000e+00\n\n* Work counters\n Solve time (sec) : 1.01304e-03\n" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "optimize!(model)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We can look at the certificate that `σ = -6` is a lower bound:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-3.000000004964362 - 1.999999998797403*x + 0.9999999995176428*x^2)^2" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "sos_dec = sos_decomposition(cref, 1e-4)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Indeed, `p + 6 = (x^2 - 2x - 3)^2` so `p ≥ -6`.\n", + "\n", + "## Extraction of minimizers\n", + "\n", + "We can now find the minimizers from the moment matrix:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 SymMatrix{Float64}:\n 1.0 0.0669168 3.13383\n 0.0669168 3.13383 6.46842\n 3.13383 6.46842 22.3383" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "ν = moment_matrix(cref)\n", + "ν.Q" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "This matrix is the convex combination of the moment matrices corresponding to two atomic measures at `-1` and `3`\n", + "which allows us to conclude that `-1` and `3` are global minimizers." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2-element Vector{Float64}:\n -1.0000001975826238\n 2.9999999542477047" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "η = atomic_measure(ν, 1e-4)\n", + "minimizers = [η.atoms[1].center; η.atoms[2].center]" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "Below are more details on what we mean by convex combination.\n", + "The moment matrix of the atomic measure at the first minimizer is:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 SymMatrix{Float64}:\n 1.0 -1.0 1.0\n -1.0 1.0 -1.0\n 1.0 -1.0 1.0" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "η1 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[1])), ν.basis.monomials)\n", + "η1.Q" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "The moment matrix of the atomic measure at the second minimizer is:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 SymMatrix{Float64}:\n 1.0 3.0 9.0\n 3.0 9.0 27.0\n 9.0 27.0 81.0" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "η2 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[2])), ν.basis.monomials)\n", + "η2.Q" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "And the moment matrix is the convex combination of both:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 Matrix{Float64}:\n 1.0 0.0669169 3.13383\n 0.0669169 3.13383 6.46842\n 3.13383 6.46842 22.3383" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "Q12 = η1.Q * η.atoms[1].weight + η2.Q * η.atoms[2].weight" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "Another way to see this (by linearity of the expectation) is that `ν` is the moment matrix\n", + "of the convex combination of the two atomic measures." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Changing the polynomial basis\n", + "\n", + "The monomial basis used by default can leave a problem quite ill-conditioned for the solver.\n", + "Let's try to use another basis instead:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 8 Ap: 9.00e-01 Pobj: -6.0000000e+00 Ad: 1.00e+00 Dobj: -6.0000000e+00 \n", + "Success: SDP solved\n", + "Primal objective value: -6.0000000e+00 \n", + "Dual objective value: -6.0000000e+00 \n", + "Relative primal infeasibility: 6.64e-12 \n", + "Relative dual infeasibility: 3.14e-10 \n", + "Real Relative Gap: 2.23e-09 \n", + "XZ Relative Gap: 3.25e-09 \n", + "DIMACS error measures: 7.25e-12 0.00e+00 5.34e-10 0.00e+00 2.23e-09 3.25e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.00e-01 Pobj: -1.8383751e+01 Ad: 7.29e-01 Dobj: -1.0343874e+01 \n", + "Iter: 2 Ap: 9.00e-01 Pobj: -1.5927039e+01 Ad: 9.00e-01 Dobj: -2.3550363e+00 \n", + "Iter: 3 Ap: 9.00e-01 Pobj: -7.7938220e+00 Ad: 9.00e-01 Dobj: -3.9182690e+00 \n", + "Iter: 4 Ap: 9.00e-01 Pobj: -6.1761570e+00 Ad: 9.00e-01 Dobj: -5.7791841e+00 \n", + "Iter: 5 Ap: 9.00e-01 Pobj: -6.0169870e+00 Ad: 9.00e-01 Dobj: -5.9771917e+00 \n", + "Iter: 6 Ap: 9.00e-01 Pobj: -6.0016653e+00 Ad: 1.00e+00 Dobj: -5.9999542e+00 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -6.0002842e+00 Ad: 1.00e+00 Dobj: -5.9997933e+00 \n", + "Iter: 8 Ap: 9.00e-01 Pobj: -6.0000531e+00 Ad: 1.00e+00 Dobj: -5.9999938e+00 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -6.0000089e+00 Ad: 1.00e+00 Dobj: -5.9999987e+00 \n", + "Iter: 10 Ap: 1.00e+00 Pobj: -6.0000012e+00 Ad: 1.00e+00 Dobj: -6.0000000e+00 \n", + "Iter: 11 Ap: 9.00e-01 Pobj: -6.0000002e+00 Ad: 1.00e+00 Dobj: -6.0000000e+00 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : -6.00000e+00\n Dual objective value : -6.00000e+00\n\n* Work counters\n Solve time (sec) : 1.55210e-03\n" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(CSDP.Optimizer)\n", + "@variable(model, σ)\n", + "@constraint(model, cheby_cref, p >= σ, basis = ChebyshevBasisFirstKind)\n", + "@objective(model, Max, σ)\n", + "optimize!(model)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "Although the gram matrix in the monomial basis:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "g.basis = MonomialBasis([1, x, x²])\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 SymMatrix{Float64}:\n 9.0 6.0 -3.0\n 6.0 4.0 -2.0\n -3.0 -2.0 1.0" + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "g = gram_matrix(cref)\n", + "@show g.basis\n", + "g.Q" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "looks different from the gram matrix in the Chebyshev basis:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cheby_g.basis = ChebyshevBasisFirstKind([1.0, x, -1.0 + 2.0x²])\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 SymMatrix{Float64}:\n 6.25 5.0 -1.25\n 5.0 4.0 -1.0\n -1.25 -1.0 0.25" + }, + "metadata": {}, + "execution_count": 13 + } + ], + "cell_type": "code", + "source": [ + "cheby_g = gram_matrix(cheby_cref)\n", + "@show cheby_g.basis\n", + "cheby_g.Q" + ], + "metadata": {}, + "execution_count": 13 + }, + { + "cell_type": "markdown", + "source": [ + "they both yields the same Sum-of-Squares decomposition:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-3.000000002974674 - 1.9999999995036628*x + 0.9999999997868867*x^2)^2" + }, + "metadata": {}, + "execution_count": 14 + } + ], + "cell_type": "code", + "source": [ + "cheby_sos_dec = sos_decomposition(cheby_cref, 1e-4)" + ], + "metadata": {}, + "execution_count": 14 + }, + { + "cell_type": "markdown", + "source": [ + "The gram matrix in the Chebyshev basis can be understood as follows.\n", + "To express the polynomial $-x^2 + 2x + 3$ in the Chebyshev basis, we start by\n", + " substituting $x$ into $\\cos(\\theta)$ to obtain\n", + "$-\\cos(\\theta)^2 + 2\\cos(\\theta) + 3$.\n", + "We now express it as a combination of $\\cos(n\\theta)$ for $n = 0, 1, 2$:\n", + "$-(2\\cos(\\theta) - 1) /2 + 2 \\cos(\\theta) + 5/2.$\n", + "Therefore, the coefficients in the Chebyshev basis is:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element Vector{Float64}:\n 2.5\n 2.0\n -0.5" + }, + "metadata": {}, + "execution_count": 15 + } + ], + "cell_type": "code", + "source": [ + "cheby_coefs = [5/2, 2, -1/2]" + ], + "metadata": {}, + "execution_count": 15 + }, + { + "cell_type": "markdown", + "source": [ + "We can indeed observe that we obtain the same matrix as `cheby_g.Q`" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3×3 Matrix{Float64}:\n 6.25 5.0 -1.25\n 5.0 4.0 -1.0\n -1.25 -1.0 0.25" + }, + "metadata": {}, + "execution_count": 16 + } + ], + "cell_type": "code", + "source": [ + "cheby_coefs * cheby_coefs'" + ], + "metadata": {}, + "execution_count": 16 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Getting started/univariate.jl b/previews/PR347/generated/Getting started/univariate.jl new file mode 100644 index 000000000..196aee31d --- /dev/null +++ b/previews/PR347/generated/Getting started/univariate.jl @@ -0,0 +1,53 @@ +using DynamicPolynomials +using SumOfSquares +import CSDP + +@polyvar x +p = x^4 - 4x^3 - 2x^2 + 12x + 3 + +model = SOSModel(CSDP.Optimizer) +@variable(model, σ) +@constraint(model, cref, p >= σ) +@objective(model, Max, σ) + +optimize!(model) +solution_summary(model) + +sos_dec = sos_decomposition(cref, 1e-4) + +ν = moment_matrix(cref) +ν.Q + +η = atomic_measure(ν, 1e-4) +minimizers = [η.atoms[1].center; η.atoms[2].center] + +η1 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[1])), ν.basis.monomials) +η1.Q + +η2 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[2])), ν.basis.monomials) +η2.Q + +Q12 = η1.Q * η.atoms[1].weight + η2.Q * η.atoms[2].weight + +model = SOSModel(CSDP.Optimizer) +@variable(model, σ) +@constraint(model, cheby_cref, p >= σ, basis = ChebyshevBasisFirstKind) +@objective(model, Max, σ) +optimize!(model) +solution_summary(model) + +g = gram_matrix(cref) +@show g.basis +g.Q + +cheby_g = gram_matrix(cheby_cref) +@show cheby_g.basis +cheby_g.Q + +cheby_sos_dec = sos_decomposition(cheby_cref, 1e-4) + +cheby_coefs = [5/2, 2, -1/2] + +cheby_coefs * cheby_coefs' + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Getting started/univariate/index.html b/previews/PR347/generated/Getting started/univariate/index.html new file mode 100644 index 000000000..da32ea458 --- /dev/null +++ b/previews/PR347/generated/Getting started/univariate/index.html @@ -0,0 +1,80 @@ + +Minimization of a univariate polynomial · SumOfSquares

Minimization of a univariate polynomial

Contributed by: Benoît Legat

using DynamicPolynomials
+using SumOfSquares
+import CSDP

Consider the problem of finding both the minimum value of p = x^4 - 4x^3 - 2x^2 + 12x + 3 as well as its minimizers.

We can use SumOfSquares.jl to find such these values as follows. We first define the polynomial using DynamicPolynomials.

@polyvar x
+p = x^4 - 4x^3 - 2x^2 + 12x + 3

\[ 3 + 12x - 2x^{2} - 4x^{3} + x^{4} \]

Secondly, we create a Sum-of-Squares program searching for the maximal lower bound σ of the polynomial.

model = SOSModel(CSDP.Optimizer)
+@variable(model, σ)
+@constraint(model, cref, p >= σ)
+@objective(model, Max, σ)

\[ σ \]

Thirdly, solve the program and find σ = -6 as lower bound:

optimize!(model)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -6.00000e+00
+  Dual objective value : -6.00000e+00
+
+* Work counters
+  Solve time (sec)   : 1.07288e-03
+

We can look at the certificate that σ = -6 is a lower bound:

sos_dec = sos_decomposition(cref, 1e-4)
(-3.000000004964362 - 1.999999998797403*x + 0.9999999995176428*x^2)^2

Indeed, p + 6 = (x^2 - 2x - 3)^2 so p ≥ -6.

Extraction of minimizers

We can now find the minimizers from the moment matrix:

ν = moment_matrix(cref)
+ν.Q
3×3 SymMatrix{Float64}:
+ 1.0        0.0669168   3.13383
+ 0.0669168  3.13383     6.46842
+ 3.13383    6.46842    22.3383

This matrix is the convex combination of the moment matrices corresponding to two atomic measures at -1 and 3 which allows us to conclude that -1 and 3 are global minimizers.

η = atomic_measure(ν, 1e-4)
+minimizers = [η.atoms[1].center; η.atoms[2].center]
2-element Vector{Float64}:
+ -1.0000001975826238
+  2.9999999542477047

Below are more details on what we mean by convex combination. The moment matrix of the atomic measure at the first minimizer is:

η1 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[1])), ν.basis.monomials)
+η1.Q
3×3 SymMatrix{Float64}:
+  1.0  -1.0   1.0
+ -1.0   1.0  -1.0
+  1.0  -1.0   1.0

The moment matrix of the atomic measure at the second minimizer is:

η2 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[2])), ν.basis.monomials)
+η2.Q
3×3 SymMatrix{Float64}:
+ 1.0   3.0   9.0
+ 3.0   9.0  27.0
+ 9.0  27.0  81.0

And the moment matrix is the convex combination of both:

Q12 = η1.Q * η.atoms[1].weight + η2.Q * η.atoms[2].weight
3×3 Matrix{Float64}:
+ 1.0        0.0669169   3.13383
+ 0.0669169  3.13383     6.46842
+ 3.13383    6.46842    22.3383

Another way to see this (by linearity of the expectation) is that ν is the moment matrix of the convex combination of the two atomic measures.

Changing the polynomial basis

The monomial basis used by default can leave a problem quite ill-conditioned for the solver. Let's try to use another basis instead:

model = SOSModel(CSDP.Optimizer)
+@variable(model, σ)
+@constraint(model, cheby_cref, p >= σ, basis = ChebyshevBasisFirstKind)
+@objective(model, Max, σ)
+optimize!(model)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -6.00000e+00
+  Dual objective value : -6.00000e+00
+
+* Work counters
+  Solve time (sec)   : 1.50895e-03
+

Although the gram matrix in the monomial basis:

g = gram_matrix(cref)
+@show g.basis
+g.Q
3×3 SymMatrix{Float64}:
+  9.0   6.0  -3.0
+  6.0   4.0  -2.0
+ -3.0  -2.0   1.0

looks different from the gram matrix in the Chebyshev basis:

cheby_g = gram_matrix(cheby_cref)
+@show cheby_g.basis
+cheby_g.Q
3×3 SymMatrix{Float64}:
+  6.25   5.0  -1.25
+  5.0    4.0  -1.0
+ -1.25  -1.0   0.25

they both yields the same Sum-of-Squares decomposition:

cheby_sos_dec = sos_decomposition(cheby_cref, 1e-4)
(-3.000000002974674 - 1.9999999995036628*x + 0.9999999997868867*x^2)^2

The gram matrix in the Chebyshev basis can be understood as follows. To express the polynomial $-x^2 + 2x + 3$ in the Chebyshev basis, we start by substituting $x$ into $\cos(\theta)$ to obtain $-\cos(\theta)^2 + 2\cos(\theta) + 3$. We now express it as a combination of $\cos(n\theta)$ for $n = 0, 1, 2$: $-(2\cos(\theta) - 1) /2 + 2 \cos(\theta) + 5/2.$ Therefore, the coefficients in the Chebyshev basis is:

cheby_coefs = [5/2, 2, -1/2]
3-element Vector{Float64}:
+  2.5
+  2.0
+ -0.5

We can indeed observe that we obtain the same matrix as cheby_g.Q

cheby_coefs * cheby_coefs'
3×3 Matrix{Float64}:
+  6.25   5.0  -1.25
+  5.0    4.0  -1.0
+ -1.25  -1.0   0.25

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables.ipynb b/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables.ipynb new file mode 100644 index 000000000..41ca439d3 --- /dev/null +++ b/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables.ipynb @@ -0,0 +1,256 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Noncommutative variables" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Examples 2.11 and 2.2 of [BKP16]\n", + "\n", + "[BKP16] Sabine Burgdorf, Igor Klep, and Janez Povh.\n", + "*Optimization of polynomials in non-commuting variables*.\n", + "Berlin: Springer, 2016." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Example 2.11\n", + "\n", + "We consider the Example 2.11 of [BKP16] in which the polynomial with noncommutative variables\n", + "$(x * y + x^2)^2 = x^4 + x^3y + xyx^2 + xyxy$ is tested to be sum-of-squares." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "xyxy + xyx² + x³y + x⁴", + "text/latex": "$$ xyxy + xyx^{2} + x^{3}y + x^{4} $$" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@ncpolyvar x y\n", + "p = (x * y + x^2)^2" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "import CSDP\n", + "optimizer_constructor = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = Model(optimizer_constructor)\n", + "con_ref = @constraint(model, p in SOSCone())\n", + "\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We see that both the monomials `xy` and `yx` are considered separately, this is a difference with the commutative version." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MonomialBasis([xy, x²])" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "certificate_basis(con_ref)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We see that the solution correctly uses the monomial `xy` instead of `yx`. We also identify that only the monomials `x^2` and `xy` would be needed. This would be dectected by the Newton chip method of [Section 2.3, BKP16]." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2×2 SymMatrix{Float64}:\n 1.0 1.0\n 1.0 1.0" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "gram_matrix(con_ref).Q" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "When asking for the SOS decomposition, the numerically small entries makes the solution less readable." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-1.0000000000000002*x*y - x^2)^2 + (-6.265166515512128e-9*x*y + 6.265166515512127e-9*x^2)^2" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "sos_decomposition(con_ref)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "They are however easily discarded by using a nonzero tolerance:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-1.0000000000000002*x*y - x^2)^2" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "sos_decomposition(con_ref, 1e-6)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "## Example 2.2\n", + "\n", + "We consider now the Example 2.2 of [BKP16] in which the polynomial with noncommutative variables\n", + "$(x + x^{10}y^{20}x^{10})^2$ is tested to be sum-of-squares." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@ncpolyvar x y\n", + "n = 10\n", + "p = (x + x^n * y^(2n) * x^n)^2\n", + "\n", + "using SumOfSquares\n", + "model = Model(optimizer_constructor)\n", + "con_ref = @constraint(model, p in SOSCone())\n", + "\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "Only two monomials were considered for the basis of the gram matrix thanks to the Augmented Newton chip method detailed in [Section 2.4, BKP16]." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-1.0000000000000002*x - x^10*y^20*x^10)^2" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "certificate_basis(con_ref)\n", + "\n", + "gram_matrix(con_ref).Q\n", + "\n", + "sos_decomposition(con_ref, 1e-6)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables.jl b/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables.jl new file mode 100644 index 000000000..fb3ea6b3e --- /dev/null +++ b/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables.jl @@ -0,0 +1,38 @@ +using DynamicPolynomials +@ncpolyvar x y +p = (x * y + x^2)^2 + +using SumOfSquares +import CSDP +optimizer_constructor = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = Model(optimizer_constructor) +con_ref = @constraint(model, p in SOSCone()) + +optimize!(model) + +certificate_basis(con_ref) + +gram_matrix(con_ref).Q + +sos_decomposition(con_ref) + +sos_decomposition(con_ref, 1e-6) + +using DynamicPolynomials +@ncpolyvar x y +n = 10 +p = (x + x^n * y^(2n) * x^n)^2 + +using SumOfSquares +model = Model(optimizer_constructor) +con_ref = @constraint(model, p in SOSCone()) + +optimize!(model) + +certificate_basis(con_ref) + +gram_matrix(con_ref).Q + +sos_decomposition(con_ref, 1e-6) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables/index.html b/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables/index.html new file mode 100644 index 000000000..a0291b33b --- /dev/null +++ b/previews/PR347/generated/Noncommutative and Hermitian/noncommutative_variables/index.html @@ -0,0 +1,25 @@ + +Noncommutative variables · SumOfSquares

Noncommutative variables

Adapted from: Examples 2.11 and 2.2 of [BKP16]

[BKP16] Sabine Burgdorf, Igor Klep, and Janez Povh. Optimization of polynomials in non-commuting variables. Berlin: Springer, 2016.

Example 2.11

We consider the Example 2.11 of [BKP16] in which the polynomial with noncommutative variables $(x * y + x^2)^2 = x^4 + x^3y + xyx^2 + xyxy$ is tested to be sum-of-squares.

using DynamicPolynomials
+@ncpolyvar x y
+p = (x * y + x^2)^2

\[ xyxy + xyx^{2} + x^{3}y + x^{4} \]

We first need to pick an SDP solver, see here for a list of the available choices.

using SumOfSquares
+import CSDP
+optimizer_constructor = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = Model(optimizer_constructor)
+con_ref = @constraint(model, p in SOSCone())
+
+optimize!(model)

We see that both the monomials xy and yx are considered separately, this is a difference with the commutative version.

certificate_basis(con_ref)
MonomialBasis([xy, x²])

We see that the solution correctly uses the monomial xy instead of yx. We also identify that only the monomials x^2 and xy would be needed. This would be dectected by the Newton chip method of [Section 2.3, BKP16].

gram_matrix(con_ref).Q
2×2 SymMatrix{Float64}:
+ 1.0  1.0
+ 1.0  1.0

When asking for the SOS decomposition, the numerically small entries makes the solution less readable.

sos_decomposition(con_ref)
(-1.0000000000000002*x*y - x^2)^2 + (-6.265166515512128e-9*x*y + 6.265166515512127e-9*x^2)^2

They are however easily discarded by using a nonzero tolerance:

sos_decomposition(con_ref, 1e-6)
(-1.0000000000000002*x*y - x^2)^2

Example 2.2

We consider now the Example 2.2 of [BKP16] in which the polynomial with noncommutative variables $(x + x^{10}y^{20}x^{10})^2$ is tested to be sum-of-squares.

using DynamicPolynomials
+@ncpolyvar x y
+n = 10
+p = (x + x^n * y^(2n) * x^n)^2
+
+using SumOfSquares
+model = Model(optimizer_constructor)
+con_ref = @constraint(model, p in SOSCone())
+
+optimize!(model)

Only two monomials were considered for the basis of the gram matrix thanks to the Augmented Newton chip method detailed in [Section 2.4, BKP16].

certificate_basis(con_ref)
+
+gram_matrix(con_ref).Q
+
+sos_decomposition(con_ref, 1e-6)
(-1.0000000000000002*x - x^10*y^20*x^10)^2

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.ipynb b/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.ipynb new file mode 100644 index 000000000..a3385351a --- /dev/null +++ b/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.ipynb @@ -0,0 +1,83 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Sums of Hermitian squares" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.00e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 2.8800000e+01 \n", + "Iter: 2 Ap: 9.00e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 5.2897959e+00 \n", + "Iter: 3 Ap: 1.00e+00 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 1.0563942e-01 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "((-1.0000000000000002 - 0.0im)*y + (0.0 - 1.0im)*x)^2" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "\n", + "using DynamicPolynomials\n", + "@ncpolyvar x y\n", + "p = (x + im * y) * (x - im * y)\n", + "\n", + "import CSDP\n", + "model = Model(CSDP.Optimizer)\n", + "cone = NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}()\n", + "con_ref = @constraint(model, p in cone)\n", + "optimize!(model)\n", + "sos_decomposition(con_ref, 1e-6)" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.jl b/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.jl new file mode 100644 index 000000000..e71cfded2 --- /dev/null +++ b/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.jl @@ -0,0 +1,14 @@ +using SumOfSquares + +using DynamicPolynomials +@ncpolyvar x y +p = (x + im * y) * (x - im * y) + +import CSDP +model = Model(CSDP.Optimizer) +cone = NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}() +con_ref = @constraint(model, p in cone) +optimize!(model) +sos_decomposition(con_ref, 1e-6) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares/index.html b/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares/index.html new file mode 100644 index 000000000..ae69f066a --- /dev/null +++ b/previews/PR347/generated/Noncommutative and Hermitian/sums_of_hermitian_squares/index.html @@ -0,0 +1,13 @@ + +Sums of Hermitian squares · SumOfSquares

Sums of Hermitian squares

Contributed by: Benoît Legat

using SumOfSquares
+
+using DynamicPolynomials
+@ncpolyvar x y
+p = (x + im * y) * (x - im * y)
+
+import CSDP
+model = Model(CSDP.Optimizer)
+cone = NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}()
+con_ref = @constraint(model, p in cone)
+optimize!(model)
+sos_decomposition(con_ref, 1e-6)
((-1.0000000000000002 - 0.0im)*y + (0.0 - 1.0im)*x)^2

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Other Applications/bounds_in_probability.ipynb b/previews/PR347/generated/Other Applications/bounds_in_probability.ipynb new file mode 100644 index 000000000..f114a0662 --- /dev/null +++ b/previews/PR347/generated/Other Applications/bounds_in_probability.ipynb @@ -0,0 +1,374 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Bounds in Probability" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: SOSTOOLS' SOSDEMO8 (See Section 4.8 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf))" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The probability adds up to one." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "μ0 = 1" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "The mean is one." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "μ1 = 1" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "The standard deviation is 1/2." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "0.5" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "σ = 1/2" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The second moment `E(x^2)` is:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1.25" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "μ2 = σ^2 + μ1^2" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We define the moments as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Measure{Float64, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}([1.0, 1.0, 1.25], DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[1, x, x²])" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x\n", + "monos = [1, x, x^2]\n", + "using SumOfSquares\n", + "μ = measure([μ0, μ1, μ2], monos)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = SOSModel(solver);" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We create a polynomial with the monomials in `monos` and\n", + "JuMP decision variables as coefficients as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1]) + (_[2])x + (_[3])x²", + "text/latex": "$$ ({\\_}_{1}) + ({\\_}_{2})x + ({\\_}_{3})x^{2} $$" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "@variable(model, poly, Poly(monos))" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "Nonnegative on the support:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1]) + (_[2])x + (_[3])x² is SOS", + "text/latex": "$$ ({\\_}_{1}) + ({\\_}_{2})x + ({\\_}_{3})x^{2} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "K = @set 0 <= x && x <= 5\n", + "con_ref = @constraint(model, poly >= 0, domain = K)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "Greater than one on the event:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1] - 1) + (_[2])x + (_[3])x² is SOS", + "text/latex": "$$ ({\\_}_{1} - 1) + ({\\_}_{2})x + ({\\_}_{3})x^{2} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "@constraint(model, poly >= 1, domain = (@set 4 <= x && x <= 5))" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "The bound (we use `LinearAlgebra` for the `⋅` syntax for the scalar product):" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "_[1] + _[2] + 1.25 _[3]", + "text/latex": "$ {\\_}_{1} + {\\_}_{2} + 1.25 {\\_}_{3} $" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra\n", + "@objective(model, Min, poly ⋅ μ)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "We verify that we found a feasible solution:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "optimize!(model)\n", + "primal_status(model)" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "The objective value is `1/37`:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "0.027027027945194515" + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "objective_value(model)" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "The solution is `(12x-11)^2 / 37^2`:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "120.9999573610103 - 263.99994311062636x + 143.99998960526992x²", + "text/latex": "$$ 120.9999573610103 - 263.99994311062636x + 143.99998960526992x^{2} $$" + }, + "metadata": {}, + "execution_count": 13 + } + ], + "cell_type": "code", + "source": [ + "value(poly) * 37^2" + ], + "metadata": {}, + "execution_count": 13 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Other Applications/bounds_in_probability.jl b/previews/PR347/generated/Other Applications/bounds_in_probability.jl new file mode 100644 index 000000000..64e9758a8 --- /dev/null +++ b/previews/PR347/generated/Other Applications/bounds_in_probability.jl @@ -0,0 +1,36 @@ +μ0 = 1 + +μ1 = 1 + +σ = 1/2 + +μ2 = σ^2 + μ1^2 + +using DynamicPolynomials +@polyvar x +monos = [1, x, x^2] +using SumOfSquares +μ = measure([μ0, μ1, μ2], monos) + +using CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +@variable(model, poly, Poly(monos)) + +K = @set 0 <= x && x <= 5 +con_ref = @constraint(model, poly >= 0, domain = K) + +@constraint(model, poly >= 1, domain = (@set 4 <= x && x <= 5)) + +using LinearAlgebra +@objective(model, Min, poly ⋅ μ) + +optimize!(model) +primal_status(model) + +objective_value(model) + +value(poly) * 37^2 + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Other Applications/bounds_in_probability/index.html b/previews/PR347/generated/Other Applications/bounds_in_probability/index.html new file mode 100644 index 000000000..80c2a3a69 --- /dev/null +++ b/previews/PR347/generated/Other Applications/bounds_in_probability/index.html @@ -0,0 +1,11 @@ + +Bounds in Probability · SumOfSquares

Bounds in Probability

Adapted from: SOSTOOLS' SOSDEMO8 (See Section 4.8 of SOSTOOLS User's Manual)

The probability adds up to one.

μ0 = 1
1

The mean is one.

μ1  = 1
1

The standard deviation is 1/2.

σ = 1/2
0.5

The second moment E(x^2) is:

μ2 = σ^2 + μ1^2
1.25

We define the moments as follows:

using DynamicPolynomials
+@polyvar x
+monos = [1, x, x^2]
+using SumOfSquares
+μ = measure([μ0, μ1, μ2], monos)
Measure{Float64, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}([1.0, 1.0, 1.25], DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[1, x, x²])

We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.

using CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = SOSModel(solver);

We create a polynomial with the monomials in monos and JuMP decision variables as coefficients as follows:

@variable(model, poly, Poly(monos))

\[ ({\_}_{1}) + ({\_}_{2})x + ({\_}_{3})x^{2} \]

Nonnegative on the support:

K = @set 0 <= x && x <= 5
+con_ref = @constraint(model, poly >= 0, domain = K)

\[ ({\_}_{1}) + ({\_}_{2})x + ({\_}_{3})x^{2} \text{ is SOS} \]

Greater than one on the event:

@constraint(model, poly >= 1, domain = (@set 4 <= x && x <= 5))

\[ ({\_}_{1} - 1) + ({\_}_{2})x + ({\_}_{3})x^{2} \text{ is SOS} \]

The bound (we use LinearAlgebra for the syntax for the scalar product):

using LinearAlgebra
+@objective(model, Min, poly ⋅ μ)

\[ {\_}_{1} + {\_}_{2} + 1.25 {\_}_{3} \]

We verify that we found a feasible solution:

optimize!(model)
+primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

The objective value is 1/37:

objective_value(model)
0.027027027945194515

The solution is (12x-11)^2 / 37^2:

value(poly) * 37^2

\[ 120.9999573610103 - 263.99994311062636x + 143.99998960526992x^{2} \]


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/bilinear.ipynb b/previews/PR347/generated/Polynomial Optimization/bilinear.ipynb new file mode 100644 index 000000000..513c7ee94 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/bilinear.ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Bilinear terms" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: [Floudas1999; Section 3.1](@cite) and [Lasserre2009; Table 5.1](@cite)" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the polynomial optimization problem from [Floudas1999; Section 3.1](@cite)." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Basic semialgebraic Set defined by no equality\n22 inequalities\n 1.0 - 0.0025*x[6] - 0.0025*x[4] ≥ 0\n 1.0 - 0.0025*x[7] - 0.0025*x[5] + 0.0025*x[4] ≥ 0\n 1.0 - 0.01*x[8] + 0.01*x[5] ≥ 0\n 83333.33333333333 - 8333.33252*x[4] - 100.0*x[1] + x[1]*x[6] ≥ 0\n -1250.0*x[5] + 1250.0*x[4] + x[2]*x[7] - x[2]*x[4] ≥ 0\n -1.25e6 + 2500.0*x[5] + x[3]*x[8] - x[3]*x[5] ≥ 0\n -100.0 + x[1] ≥ 0\n 10000.0 - x[1] ≥ 0\n -1000.0 + x[2] ≥ 0\n 10000.0 - x[2] ≥ 0\n -1000.0 + x[3] ≥ 0\n 10000.0 - x[3] ≥ 0\n -10.0 + x[4] ≥ 0\n 1000.0 - x[4] ≥ 0\n -10.0 + x[5] ≥ 0\n 1000.0 - x[5] ≥ 0\n -10.0 + x[6] ≥ 0\n 1000.0 - x[6] ≥ 0\n -10.0 + x[7] ≥ 0\n 1000.0 - x[7] ≥ 0\n -10.0 + x[8] ≥ 0\n 1000.0 - x[8] ≥ 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:8]\n", + "p = sum(x[1:3])\n", + "using SumOfSquares\n", + "K = @set 0.0025 * (x[4] + x[6]) <= 1 &&\n", + " 0.0025 * (-x[4] + x[5] + x[7]) <= 1 &&\n", + " 0.01 * (-x[5] + x[8]) <= 1 &&\n", + " 100x[1] - x[1] * x[6] + 8333.33252x[4] <= 250000/3 &&\n", + " x[2] * x[4] - x[2] * x[7] - 1250x[4] + 1250x[5] <= 0 &&\n", + " x[3] * x[5] - x[3] * x[8] - 2500x[5] + 1250000 <= 0 &&\n", + " 100 <= x[1] && x[1] <= 10000 &&\n", + " 1000 <= x[2] && x[2] <= 10000 &&\n", + " 1000 <= x[3] && x[3] <= 10000 &&\n", + " 10 <= x[4] && x[4] <= 1000 &&\n", + " 10 <= x[5] && x[5] <= 1000 &&\n", + " 10 <= x[6] && x[6] <= 1000 &&\n", + " 10 <= x[7] && x[7] <= 1000 &&\n", + " 10 <= x[8] && x[8] <= 1000" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Clarabel.MOIwrapper.Optimizer" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import Clarabel\n", + "solver = Clarabel.Optimizer" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "solve (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "function solve(d)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = K, maxdegree = d)\n", + " optimize!(model)\n", + " println(solution_summary(model))\n", + " return model\n", + "end" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The first level of the hierarchy gives a lower bound of `2100`" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 21\n", + " constraints = 29\n", + " nnz(P) = 0\n", + " nnz(A) = 64\n", + " cones (total) = 2\n", + " : Zero = 1, numel = 9\n", + " : Nonnegative = 1, numel = 20\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 -2.3512e+03 -2.3512e+03 1.93e-16 2.04e-02 5.29e-02 1.00e+00 9.80e+01 ------ \n", + " 1 -2.1101e+03 -2.1100e+03 9.17e-06 5.10e-04 9.42e-04 3.70e-02 1.86e+00 9.81e-01 \n", + " 2 -2.1001e+03 -2.1001e+03 9.66e-08 5.27e-06 9.66e-06 3.84e-04 1.93e-02 9.90e-01 \n", + " 3 -2.1000e+03 -2.1000e+03 9.66e-10 5.27e-08 9.66e-08 3.84e-06 1.93e-04 9.90e-01 \n", + " 4 -2.1000e+03 -2.1000e+03 9.66e-12 5.27e-10 9.66e-10 3.84e-08 1.93e-06 9.90e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 112ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : 2.10000e+03\n", + " Dual objective value : 2.10000e+03\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 1.12440e-01\n", + " Barrier iterations : 4\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model2 = solve(2)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/bilinear.jl b/previews/PR347/generated/Polynomial Optimization/bilinear.jl new file mode 100644 index 000000000..4eff58bd8 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/bilinear.jl @@ -0,0 +1,36 @@ +using DynamicPolynomials +@polyvar x[1:8] +p = sum(x[1:3]) +using SumOfSquares +K = @set 0.0025 * (x[4] + x[6]) <= 1 && + 0.0025 * (-x[4] + x[5] + x[7]) <= 1 && + 0.01 * (-x[5] + x[8]) <= 1 && + 100x[1] - x[1] * x[6] + 8333.33252x[4] <= 250000/3 && + x[2] * x[4] - x[2] * x[7] - 1250x[4] + 1250x[5] <= 0 && + x[3] * x[5] - x[3] * x[8] - 2500x[5] + 1250000 <= 0 && + 100 <= x[1] && x[1] <= 10000 && + 1000 <= x[2] && x[2] <= 10000 && + 1000 <= x[3] && x[3] <= 10000 && + 10 <= x[4] && x[4] <= 1000 && + 10 <= x[5] && x[5] <= 1000 && + 10 <= x[6] && x[6] <= 1000 && + 10 <= x[7] && x[7] <= 1000 && + 10 <= x[8] && x[8] <= 1000 + +import Clarabel +solver = Clarabel.Optimizer + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +model2 = solve(2) +nothing # hide + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/bilinear/index.html b/previews/PR347/generated/Polynomial Optimization/bilinear/index.html new file mode 100644 index 000000000..fd6d844d7 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/bilinear/index.html @@ -0,0 +1,104 @@ + +Bilinear terms · SumOfSquares

Bilinear terms

Adapted from: (Floudas et al., 1999; Section 3.1) and (Lasserre, 2009; Table 5.1)

Introduction

Consider the polynomial optimization problem from (Floudas et al., 1999; Section 3.1).

using DynamicPolynomials
+@polyvar x[1:8]
+p = sum(x[1:3])
+using SumOfSquares
+K = @set 0.0025 * (x[4] + x[6]) <= 1 &&
+    0.0025 * (-x[4] + x[5] + x[7]) <= 1 &&
+    0.01 * (-x[5] + x[8]) <= 1 &&
+    100x[1] - x[1] * x[6] + 8333.33252x[4] <= 250000/3 &&
+    x[2] * x[4] - x[2] * x[7] - 1250x[4] + 1250x[5] <= 0 &&
+    x[3] * x[5] - x[3] * x[8] - 2500x[5] + 1250000 <= 0 &&
+    100 <= x[1] && x[1] <= 10000 &&
+    1000 <= x[2] && x[2] <= 10000 &&
+    1000 <= x[3] && x[3] <= 10000 &&
+    10 <= x[4] && x[4] <= 1000 &&
+    10 <= x[5] && x[5] <= 1000 &&
+    10 <= x[6] && x[6] <= 1000 &&
+    10 <= x[7] && x[7] <= 1000 &&
+    10 <= x[8] && x[8] <= 1000
Basic semialgebraic Set defined by no equality
+22 inequalities
+ 1.0 - 0.0025*x[6] - 0.0025*x[4] ≥ 0
+ 1.0 - 0.0025*x[7] - 0.0025*x[5] + 0.0025*x[4] ≥ 0
+ 1.0 - 0.01*x[8] + 0.01*x[5] ≥ 0
+ 83333.33333333333 - 8333.33252*x[4] - 100.0*x[1] + x[1]*x[6] ≥ 0
+ -1250.0*x[5] + 1250.0*x[4] + x[2]*x[7] - x[2]*x[4] ≥ 0
+ -1.25e6 + 2500.0*x[5] + x[3]*x[8] - x[3]*x[5] ≥ 0
+ -100.0 + x[1] ≥ 0
+ 10000.0 - x[1] ≥ 0
+ -1000.0 + x[2] ≥ 0
+ 10000.0 - x[2] ≥ 0
+ -1000.0 + x[3] ≥ 0
+ 10000.0 - x[3] ≥ 0
+ -10.0 + x[4] ≥ 0
+ 1000.0 - x[4] ≥ 0
+ -10.0 + x[5] ≥ 0
+ 1000.0 - x[5] ≥ 0
+ -10.0 + x[6] ≥ 0
+ 1000.0 - x[6] ≥ 0
+ -10.0 + x[7] ≥ 0
+ 1000.0 - x[7] ≥ 0
+ -10.0 + x[8] ≥ 0
+ 1000.0 - x[8] ≥ 0
+

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import Clarabel
+solver = Clarabel.Optimizer
Clarabel.MOIwrapper.Optimizer

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.

function solve(d)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = K, maxdegree = d)
+    optimize!(model)
+    println(solution_summary(model))
+    return model
+end
solve (generic function with 1 method)

The first level of the hierarchy gives a lower bound of 2100

model2 = solve(2)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 21
+  constraints   = 29
+  nnz(P)        = 0
+  nnz(A)        = 64
+  cones (total) = 2
+    : Zero        = 1,  numel = 9
+    : Nonnegative = 1,  numel = 20
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0  -2.3512e+03  -2.3512e+03  1.93e-16  2.04e-02  5.29e-02  1.00e+00  9.80e+01   ------
+  1  -2.1101e+03  -2.1100e+03  9.17e-06  5.10e-04  9.42e-04  3.70e-02  1.86e+00  9.81e-01
+  2  -2.1001e+03  -2.1001e+03  9.66e-08  5.27e-06  9.66e-06  3.84e-04  1.93e-02  9.90e-01
+  3  -2.1000e+03  -2.1000e+03  9.66e-10  5.27e-08  9.66e-08  3.84e-06  1.93e-04  9.90e-01
+  4  -2.1000e+03  -2.1000e+03  9.66e-12  5.27e-10  9.66e-10  3.84e-08  1.93e-06  9.90e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time =  946μs
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 2.10000e+03
+  Dual objective value : 2.10000e+03
+
+* Work counters
+  Solve time (sec)   : 9.45726e-04
+  Barrier iterations : 4

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum.ipynb b/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum.ipynb new file mode 100644 index 000000000..8920ed232 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum.ipynb @@ -0,0 +1,208 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Bound on Global Extremum" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: SOSTOOLS' SOSDEMO3 (See Section 4.3 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf))" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(x1, x2)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x1 x2" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "The Goldstein-Price function $f(x)$ is defined as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "600 + 720x2 + 720x1 + 3060x2² - 4680x1x2 + 1260x1² + 12288x2³ - 19296x1x2² + 7344x1²x2 - 1072x1³ + 14346x2⁴ - 23616x1x2³ + 7776x1²x2² + 5784x1³x2 - 2454x1⁴ + 1944x2⁵ - 11880x1x2⁴ + 5040x1²x2³ + 9840x1³x2² - 7680x1⁴x2 + 1344x1⁵ - 4428x2⁶ - 1188x1x2⁵ + 8730x1²x2⁴ + 1240x1³x2³ - 5370x1⁴x2² - 168x1⁵x2 + 952x1⁶ - 648x2⁷ + 1944x1x2⁶ + 3672x1²x2⁵ - 3480x1³x2⁴ - 4080x1⁴x2³ + 2592x1⁵x2² + 1344x1⁶x2 - 768x1⁷ + 729x2⁸ + 972x1x2⁷ - 1458x1²x2⁶ - 1836x1³x2⁵ + 1305x1⁴x2⁴ + 1224x1⁵x2³ - 648x1⁶x2² - 288x1⁷x2 + 144x1⁸", + "text/latex": "$$ 600 + 720x2 + 720x1 + 3060x2^{2} - 4680x1x2 + 1260x1^{2} + 12288x2^{3} - 19296x1x2^{2} + 7344x1^{2}x2 - 1072x1^{3} + 14346x2^{4} - 23616x1x2^{3} + 7776x1^{2}x2^{2} + 5784x1^{3}x2 - 2454x1^{4} + 1944x2^{5} - 11880x1x2^{4} + 5040x1^{2}x2^{3} + 9840x1^{3}x2^{2} - 7680x1^{4}x2 + 1344x1^{5} - 4428x2^{6} - 1188x1x2^{5} + 8730x1^{2}x2^{4} + 1240x1^{3}x2^{3} - 5370x1^{4}x2^{2} - 168x1^{5}x2 + 952x1^{6} - 648x2^{7} + 1944x1x2^{6} + 3672x1^{2}x2^{5} - 3480x1^{3}x2^{4} - 4080x1^{4}x2^{3} + 2592x1^{5}x2^{2} + 1344x1^{6}x2 - 768x1^{7} + 729x2^{8} + 972x1x2^{7} - 1458x1^{2}x2^{6} - 1836x1^{3}x2^{5} + 1305x1^{4}x2^{4} + 1224x1^{5}x2^{3} - 648x1^{6}x2^{2} - 288x1^{7}x2 + 144x1^{8} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "f1 = x1 + x2 + 1\n", + "f2 = 19 - 14x1 + 3x1^2 - 14x2 + 6x1*x2 + 3x2^2\n", + "f3 = 2x1 - 3x2\n", + "f4 = 18 - 32x1 + 12x1^2 + 48x2 - 36x1*x2 + 27x2^2\n", + "f = (1 + f1^2 * f2) * (30 + f3^2 * f4)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "using CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = SOSModel(solver);" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We create the decision variable $\\gamma$ that will be the lower bound to the Goldstein-Price function.\n", + "We maximize it to have the highest possible lower bound." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "γ", + "text/latex": "$ γ $" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "@variable(model, γ)\n", + "@objective(model, Max, γ)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We constrain $\\gamma$ to be a lower bound with the following constraint\n", + "that ensures that $f(x_1, x_2) \\ge \\gamma$ for all $x_1, x_2$." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "@constraint(model, f >= γ)\n", + "\n", + "JuMP.optimize!(model)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We verify that the solver has found a feasible solution:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "NEARLY_FEASIBLE_POINT::ResultStatusCode = 2" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "JuMP.primal_status(model)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We can now obtain the lower bound either with `value(γ)` or `objective_value(model)`:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2.999986072324649" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "objective_value(model)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum.jl b/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum.jl new file mode 100644 index 000000000..07945aea0 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum.jl @@ -0,0 +1,26 @@ +using DynamicPolynomials +@polyvar x1 x2 + +f1 = x1 + x2 + 1 +f2 = 19 - 14x1 + 3x1^2 - 14x2 + 6x1*x2 + 3x2^2 +f3 = 2x1 - 3x2 +f4 = 18 - 32x1 + 12x1^2 + 48x2 - 36x1*x2 + 27x2^2 +f = (1 + f1^2 * f2) * (30 + f3^2 * f4) + +using SumOfSquares +using CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +@variable(model, γ) +@objective(model, Max, γ) + +@constraint(model, f >= γ) + +JuMP.optimize!(model) + +JuMP.primal_status(model) + +objective_value(model) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum/index.html b/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum/index.html new file mode 100644 index 000000000..3c7435952 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/bound_on_global_extremum/index.html @@ -0,0 +1,13 @@ + +Bound on Global Extremum · SumOfSquares

Bound on Global Extremum

Adapted from: SOSTOOLS' SOSDEMO3 (See Section 4.3 of SOSTOOLS User's Manual)

using DynamicPolynomials
+@polyvar x1 x2
(x1, x2)

The Goldstein-Price function $f(x)$ is defined as follows:

f1 = x1 + x2 + 1
+f2 = 19 - 14x1 + 3x1^2 - 14x2 + 6x1*x2 + 3x2^2
+f3 = 2x1 - 3x2
+f4 = 18 - 32x1 + 12x1^2 + 48x2 - 36x1*x2 + 27x2^2
+f = (1 + f1^2 * f2) * (30 + f3^2 * f4)

\[ 600 + 720x2 + 720x1 + 3060x2^{2} - 4680x1x2 + 1260x1^{2} + 12288x2^{3} - 19296x1x2^{2} + 7344x1^{2}x2 - 1072x1^{3} + 14346x2^{4} - 23616x1x2^{3} + 7776x1^{2}x2^{2} + 5784x1^{3}x2 - 2454x1^{4} + 1944x2^{5} - 11880x1x2^{4} + 5040x1^{2}x2^{3} + 9840x1^{3}x2^{2} - 7680x1^{4}x2 + 1344x1^{5} - 4428x2^{6} - 1188x1x2^{5} + 8730x1^{2}x2^{4} + 1240x1^{3}x2^{3} - 5370x1^{4}x2^{2} - 168x1^{5}x2 + 952x1^{6} - 648x2^{7} + 1944x1x2^{6} + 3672x1^{2}x2^{5} - 3480x1^{3}x2^{4} - 4080x1^{4}x2^{3} + 2592x1^{5}x2^{2} + 1344x1^{6}x2 - 768x1^{7} + 729x2^{8} + 972x1x2^{7} - 1458x1^{2}x2^{6} - 1836x1^{3}x2^{5} + 1305x1^{4}x2^{4} + 1224x1^{5}x2^{3} - 648x1^{6}x2^{2} - 288x1^{7}x2 + 144x1^{8} \]

We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.

using SumOfSquares
+using CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = SOSModel(solver);

We create the decision variable $\gamma$ that will be the lower bound to the Goldstein-Price function. We maximize it to have the highest possible lower bound.

@variable(model, γ)
+@objective(model, Max, γ)

\[ γ \]

We constrain $\gamma$ to be a lower bound with the following constraint that ensures that $f(x_1, x_2) \ge \gamma$ for all $x_1, x_2$.

@constraint(model, f >= γ)
+
+JuMP.optimize!(model)

We verify that the solver has found a feasible solution:

JuMP.primal_status(model)
NEARLY_FEASIBLE_POINT::ResultStatusCode = 2

We can now obtain the lower bound either with value(γ) or objective_value(model):

objective_value(model)
2.999986072324649

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/ellipsoid.ipynb b/previews/PR347/generated/Polynomial Optimization/ellipsoid.ipynb new file mode 100644 index 000000000..4756700b1 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/ellipsoid.ipynb @@ -0,0 +1,497 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Exterior of ellipsoid" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: [Floudas1999; Section 3.5](@cite) and [Lasserre2009; Table 5.1](@cite)" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the polynomial optimization problem from [Floudas1999; Section 3.5](@cite)" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Basic semialgebraic Set defined by no equality\n8 inequalities\n 4.0 - x[3] - x[2] - x[1] ≥ 0\n 6.0 - x[3] - 3.0*x[2] ≥ 0\n 24.0 - 13.0*x[3] + 9.0*x[2] - 20.0*x[1] + 2.0*x[3]^2 - 2.0*x[2]*x[3] + 2.0*x[2]^2 + 4.0*x[1]*x[3] - 4.0*x[1]*x[2] + 4.0*x[1]^2 ≥ 0\n x[1] ≥ 0\n 2.0 - x[1] ≥ 0\n x[2] ≥ 0\n x[3] ≥ 0\n 3.0 - x[3] ≥ 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "A = [\n", + " 0 0 1\n", + " 0 -1 0\n", + " -2 1 -1\n", + "]\n", + "bz = [3, 0, -4] - [0, -1, -6]\n", + "y = [1.5, -0.5, -5]\n", + "\n", + "using DynamicPolynomials\n", + "@polyvar x[1:3]\n", + "p = -2x[1] + x[2] - x[3]\n", + "using SumOfSquares\n", + "e = A * x - y\n", + "f = e'e - bz'bz / 4\n", + "K = @set sum(x) <= 4 && 3x[2] + x[3] <= 6 && f >= 0 && 0 <= x[1] && x[1] <= 2 && 0 <= x[2] && 0 <= x[3] && x[3] <= 3" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Clarabel.MOIwrapper.Optimizer" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import Clarabel\n", + "solver = Clarabel.Optimizer" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "solve (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "function solve(d)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = K, maxdegree = d)\n", + " optimize!(model)\n", + " println(solution_summary(model))\n", + " return model\n", + "end" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The first level of the hierarchy gives a lower bound of `-7``" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 9\n", + " constraints = 12\n", + " nnz(P) = 0\n", + " nnz(A) = 24\n", + " cones (total) = 2\n", + " : Zero = 1, numel = 4\n", + " : Nonnegative = 1, numel = 8\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 2.2646e+00 2.2646e+00 0.00e+00 5.04e-01 2.23e-01 1.00e+00 2.84e+00 ------ \n", + " 1 4.8146e+00 4.8773e+00 1.30e-02 1.11e-01 3.74e-02 2.33e-01 6.39e-01 8.00e-01 \n", + " 2 5.8894e+00 5.8986e+00 1.56e-03 1.43e-02 4.91e-03 3.33e-02 9.41e-02 8.57e-01 \n", + " 3 5.9970e+00 5.9972e+00 3.18e-05 2.67e-04 9.33e-05 6.56e-04 1.82e-03 9.81e-01 \n", + " 4 6.0000e+00 6.0000e+00 3.18e-07 2.67e-06 9.32e-07 6.56e-06 1.82e-05 9.90e-01 \n", + " 5 6.0000e+00 6.0000e+00 3.18e-09 2.67e-08 9.32e-09 6.56e-08 1.82e-07 9.90e-01 \n", + " 6 6.0000e+00 6.0000e+00 3.18e-11 2.67e-10 9.32e-11 6.56e-10 1.82e-09 9.90e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 2.61ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -6.00000e+00\n", + " Dual objective value : -6.00000e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 2.61375e-03\n", + " Barrier iterations : 6\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model2 = solve(2)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "The second level improves the lower bound" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 82\n", + " constraints = 101\n", + " nnz(P) = 0\n", + " nnz(A) = 242\n", + " cones (total) = 10\n", + " : Zero = 1, numel = 20\n", + " : Nonnegative = 1, numel = 1\n", + " : PSDTriangle = 8, numel = (10,10,10,10,...,10)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 9.7795e-01 9.7795e-01 1.11e-16 6.53e-01 4.62e-01 1.00e+00 2.05e+00 ------ \n", + " 1 1.2254e+00 1.2350e+00 7.85e-03 1.33e-01 7.13e-02 1.75e-01 4.77e-01 7.96e-01 \n", + " 2 2.6674e+00 2.7439e+00 2.87e-02 6.88e-02 2.81e-02 1.71e-01 2.05e-01 7.36e-01 \n", + " 3 4.3661e+00 4.4172e+00 1.17e-02 1.60e-02 5.48e-03 7.83e-02 4.58e-02 8.30e-01 \n", + " 4 5.1102e+00 5.1418e+00 6.18e-03 7.99e-03 2.62e-03 4.73e-02 2.38e-02 5.82e-01 \n", + " 5 5.5386e+00 5.5472e+00 1.54e-03 2.33e-03 7.37e-04 1.33e-02 7.23e-03 7.49e-01 \n", + " 6 5.6457e+00 5.6476e+00 3.40e-04 5.12e-04 1.62e-04 3.00e-03 1.66e-03 8.07e-01 \n", + " 7 5.6906e+00 5.6907e+00 1.34e-05 1.98e-05 6.26e-06 1.19e-04 6.47e-05 9.72e-01 \n", + " 8 5.6922e+00 5.6922e+00 8.64e-07 1.27e-06 4.02e-07 7.63e-06 4.16e-06 9.40e-01 \n", + " 9 5.6923e+00 5.6923e+00 1.21e-08 1.76e-08 5.58e-09 1.06e-07 5.77e-08 9.87e-01 \n", + " 10 5.6923e+00 5.6923e+00 2.66e-10 3.80e-10 1.21e-10 2.33e-09 1.25e-09 9.78e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 60.1ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -5.69231e+00\n", + " Dual objective value : -5.69231e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 6.01229e-02\n", + " Barrier iterations : 10\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model4 = solve(4)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "The third level improves it even further" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 451\n", + " constraints = 506\n", + " nnz(P) = 0\n", + " nnz(A) = 1376\n", + " cones (total) = 10\n", + " : Zero = 1, numel = 56\n", + " : PSDTriangle = 9, numel = (55,55,10,55,...,55)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 6.2703e-01 6.2703e-01 0.00e+00 7.56e-01 5.36e-01 1.00e+00 1.48e+00 ------ \n", + " 1 7.4953e-01 7.6135e-01 1.18e-02 1.58e-01 9.97e-02 2.39e-01 4.26e-01 8.06e-01 \n", + " 2 1.2333e+00 1.3121e+00 6.39e-02 4.31e-02 2.64e-02 1.73e-01 1.70e-01 8.68e-01 \n", + " 3 1.9671e+00 2.0062e+00 1.99e-02 1.22e-02 4.68e-03 6.32e-02 3.87e-02 8.18e-01 \n", + " 4 2.7047e+00 2.7536e+00 1.81e-02 8.45e-03 2.26e-03 6.99e-02 1.94e-02 7.43e-01 \n", + " 5 3.0495e+00 3.0614e+00 3.90e-03 3.75e-03 9.47e-04 2.13e-02 8.43e-03 9.22e-01 \n", + " 6 3.4706e+00 3.4774e+00 1.96e-03 9.59e-04 2.24e-04 9.63e-03 1.95e-03 8.04e-01 \n", + " 7 3.7081e+00 3.7129e+00 1.30e-03 4.91e-04 1.15e-04 6.51e-03 9.26e-04 6.34e-01 \n", + " 8 3.9158e+00 3.9173e+00 3.71e-04 1.29e-04 3.04e-05 1.93e-03 2.38e-04 8.24e-01 \n", + " 9 3.9469e+00 3.9488e+00 4.92e-04 8.66e-05 1.55e-05 2.34e-03 1.30e-04 6.86e-01 \n", + " 10 4.0073e+00 4.0086e+00 3.31e-04 3.98e-05 5.09e-06 1.52e-03 4.86e-05 7.76e-01 \n", + " 11 4.0267e+00 4.0275e+00 1.76e-04 1.93e-05 2.66e-06 8.15e-04 2.55e-05 7.35e-01 \n", + " 12 4.0582e+00 4.0584e+00 3.91e-05 3.52e-06 4.53e-07 1.79e-04 4.47e-06 9.70e-01 \n", + " 13 4.0660e+00 4.0660e+00 1.14e-05 9.59e-07 1.23e-07 5.20e-05 1.22e-06 8.03e-01 \n", + " 14 4.0671e+00 4.0671e+00 6.05e-06 4.79e-07 6.23e-08 2.75e-05 6.16e-07 6.69e-01 \n", + " 15 4.0683e+00 4.0683e+00 7.91e-07 6.17e-08 8.06e-09 3.60e-06 7.98e-08 8.78e-01 \n", + " 16 4.0684e+00 4.0684e+00 3.27e-07 2.44e-08 3.20e-09 1.48e-06 3.17e-08 7.67e-01 \n", + " 17 4.0685e+00 4.0685e+00 6.90e-09 5.14e-10 6.73e-11 3.12e-08 6.67e-10 9.80e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 64.0ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -4.06848e+00\n", + " Dual objective value : -4.06848e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 6.40200e-02\n", + " Barrier iterations : 17\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model6 = solve(6)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "The fourth level finds the optimal objective value as lower bound." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 1813\n", + " constraints = 1938\n", + " nnz(P) = 0\n", + " nnz(A) = 5689\n", + " cones (total) = 10\n", + " : Zero = 1, numel = 126\n", + " : PSDTriangle = 9, numel = (210,210,66,210,...,276)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 5.6617e-01 5.6617e-01 4.44e-16 8.17e-01 7.34e-01 1.00e+00 1.32e+00 ------ \n", + " 1 6.4674e-01 6.4734e-01 6.01e-04 1.62e-01 1.39e-01 2.54e-01 4.12e-01 7.90e-01 \n", + " 2 8.6375e-01 9.4985e-01 8.61e-02 6.23e-02 5.34e-02 2.30e-01 2.32e-01 7.49e-01 \n", + " 3 1.3638e+00 1.3968e+00 2.41e-02 1.40e-02 8.73e-03 6.36e-02 5.21e-02 9.26e-01 \n", + " 4 2.0678e+00 2.0994e+00 1.53e-02 5.77e-03 2.46e-03 4.79e-02 1.82e-02 7.97e-01 \n", + " 5 2.3355e+00 2.3550e+00 8.36e-03 3.83e-03 1.37e-03 3.02e-02 1.09e-02 5.39e-01 \n", + " 6 2.7753e+00 2.7885e+00 4.75e-03 1.63e-03 4.62e-04 1.85e-02 4.07e-03 7.19e-01 \n", + " 7 3.1431e+00 3.1447e+00 5.16e-04 5.25e-04 1.36e-04 3.42e-03 1.30e-03 9.52e-01 \n", + " 8 3.2519e+00 3.2544e+00 7.58e-04 3.30e-04 8.17e-05 3.94e-03 7.58e-04 6.30e-01 \n", + " 9 3.3335e+00 3.3356e+00 6.53e-04 2.40e-04 5.77e-05 3.31e-03 5.40e-04 5.27e-01 \n", + " 10 3.5632e+00 3.5650e+00 5.04e-04 7.97e-05 1.71e-05 2.29e-03 1.62e-04 7.81e-01 \n", + " 11 3.6267e+00 3.6288e+00 5.82e-04 6.38e-05 1.32e-05 2.58e-03 1.22e-04 4.53e-01 \n", + " 12 3.8605e+00 3.8614e+00 2.08e-04 2.21e-05 4.24e-06 9.82e-04 4.09e-05 7.15e-01 \n", + " 13 3.9773e+00 3.9775e+00 2.96e-05 3.42e-06 6.21e-07 1.45e-04 6.28e-06 8.75e-01 \n", + " 14 3.9966e+00 3.9967e+00 5.04e-06 4.70e-07 8.32e-08 2.39e-05 8.76e-07 9.42e-01 \n", + " 15 3.9996e+00 3.9996e+00 6.22e-07 5.44e-08 9.54e-09 2.92e-06 1.02e-07 9.37e-01 \n", + " 16 4.0000e+00 4.0000e+00 5.81e-08 5.04e-09 8.81e-10 2.72e-07 9.45e-09 9.08e-01 \n", + " 17 4.0000e+00 4.0000e+00 1.74e-08 1.45e-09 2.52e-10 8.10e-08 2.71e-09 8.55e-01 \n", + " 18 4.0000e+00 4.0000e+00 2.70e-09 3.35e-10 3.91e-11 1.26e-08 4.19e-10 8.51e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 846ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -4.00000e+00\n", + " Dual objective value : -4.00000e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 8.45558e-01\n", + " Barrier iterations : 18\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model8 = solve(8)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/ellipsoid.jl b/previews/PR347/generated/Polynomial Optimization/ellipsoid.jl new file mode 100644 index 000000000..46816203f --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/ellipsoid.jl @@ -0,0 +1,42 @@ +A = [ + 0 0 1 + 0 -1 0 + -2 1 -1 +] +bz = [3, 0, -4] - [0, -1, -6] +y = [1.5, -0.5, -5] + +using DynamicPolynomials +@polyvar x[1:3] +p = -2x[1] + x[2] - x[3] +using SumOfSquares +e = A * x - y +f = e'e - bz'bz / 4 +K = @set sum(x) <= 4 && 3x[2] + x[3] <= 6 && f >= 0 && 0 <= x[1] && x[1] <= 2 && 0 <= x[2] && 0 <= x[3] && x[3] <= 3 + +import Clarabel +solver = Clarabel.Optimizer + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +model2 = solve(2) +nothing # hide + +model4 = solve(4) +nothing # hide + +model6 = solve(6) +nothing # hide + +model8 = solve(8) +nothing # hide + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/ellipsoid/index.html b/previews/PR347/generated/Polynomial Optimization/ellipsoid/index.html new file mode 100644 index 000000000..80ab36b1e --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/ellipsoid/index.html @@ -0,0 +1,279 @@ + +Exterior of ellipsoid · SumOfSquares

Exterior of ellipsoid

Adapted from: (Floudas et al., 1999; Section 3.5) and (Lasserre, 2009; Table 5.1)

Introduction

Consider the polynomial optimization problem from (Floudas et al., 1999; Section 3.5)

A = [
+     0  0  1
+     0 -1  0
+    -2  1 -1
+]
+bz = [3, 0, -4] - [0, -1, -6]
+y = [1.5, -0.5, -5]
+
+using DynamicPolynomials
+@polyvar x[1:3]
+p = -2x[1] + x[2] - x[3]
+using SumOfSquares
+e = A * x - y
+f = e'e - bz'bz / 4
+K = @set sum(x) <= 4 && 3x[2] + x[3] <= 6 && f >= 0 && 0 <= x[1] && x[1] <= 2 && 0 <= x[2] && 0 <= x[3] && x[3] <= 3
Basic semialgebraic Set defined by no equality
+8 inequalities
+ 4.0 - x[3] - x[2] - x[1] ≥ 0
+ 6.0 - x[3] - 3.0*x[2] ≥ 0
+ 24.0 - 13.0*x[3] + 9.0*x[2] - 20.0*x[1] + 2.0*x[3]^2 - 2.0*x[2]*x[3] + 2.0*x[2]^2 + 4.0*x[1]*x[3] - 4.0*x[1]*x[2] + 4.0*x[1]^2 ≥ 0
+ x[1] ≥ 0
+ 2.0 - x[1] ≥ 0
+ x[2] ≥ 0
+ x[3] ≥ 0
+ 3.0 - x[3] ≥ 0
+

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import Clarabel
+solver = Clarabel.Optimizer
Clarabel.MOIwrapper.Optimizer

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.

function solve(d)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = K, maxdegree = d)
+    optimize!(model)
+    println(solution_summary(model))
+    return model
+end
solve (generic function with 1 method)

The first level of the hierarchy gives a lower bound of -7`

model2 = solve(2)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 9
+  constraints   = 12
+  nnz(P)        = 0
+  nnz(A)        = 24
+  cones (total) = 2
+    : Zero        = 1,  numel = 4
+    : Nonnegative = 1,  numel = 8
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   2.2646e+00   2.2646e+00  0.00e+00  5.04e-01  2.23e-01  1.00e+00  2.84e+00   ------
+  1   4.8146e+00   4.8773e+00  1.30e-02  1.11e-01  3.74e-02  2.33e-01  6.39e-01  8.00e-01
+  2   5.8894e+00   5.8986e+00  1.56e-03  1.43e-02  4.91e-03  3.33e-02  9.41e-02  8.57e-01
+  3   5.9970e+00   5.9972e+00  3.18e-05  2.67e-04  9.33e-05  6.56e-04  1.82e-03  9.81e-01
+  4   6.0000e+00   6.0000e+00  3.18e-07  2.67e-06  9.32e-07  6.56e-06  1.82e-05  9.90e-01
+  5   6.0000e+00   6.0000e+00  3.18e-09  2.67e-08  9.32e-09  6.56e-08  1.82e-07  9.90e-01
+  6   6.0000e+00   6.0000e+00  3.18e-11  2.67e-10  9.32e-11  6.56e-10  1.82e-09  9.90e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 32.3ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -6.00000e+00
+  Dual objective value : -6.00000e+00
+
+* Work counters
+  Solve time (sec)   : 3.22872e-02
+  Barrier iterations : 6

The second level improves the lower bound

model4 = solve(4)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 82
+  constraints   = 101
+  nnz(P)        = 0
+  nnz(A)        = 242
+  cones (total) = 10
+    : Zero        = 1,  numel = 20
+    : Nonnegative = 1,  numel = 1
+    : PSDTriangle = 8,  numel = (10,10,10,10,...,10)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   9.7795e-01   9.7795e-01  1.11e-16  6.53e-01  4.62e-01  1.00e+00  2.05e+00   ------
+  1   1.2254e+00   1.2350e+00  7.85e-03  1.33e-01  7.13e-02  1.75e-01  4.77e-01  7.96e-01
+  2   2.6674e+00   2.7439e+00  2.87e-02  6.88e-02  2.81e-02  1.71e-01  2.05e-01  7.36e-01
+  3   4.3661e+00   4.4172e+00  1.17e-02  1.60e-02  5.48e-03  7.83e-02  4.58e-02  8.30e-01
+  4   5.1102e+00   5.1418e+00  6.18e-03  7.99e-03  2.62e-03  4.73e-02  2.38e-02  5.82e-01
+  5   5.5386e+00   5.5472e+00  1.54e-03  2.33e-03  7.37e-04  1.33e-02  7.23e-03  7.49e-01
+  6   5.6457e+00   5.6476e+00  3.40e-04  5.12e-04  1.62e-04  3.00e-03  1.66e-03  8.07e-01
+  7   5.6906e+00   5.6907e+00  1.34e-05  1.98e-05  6.26e-06  1.19e-04  6.47e-05  9.72e-01
+  8   5.6922e+00   5.6922e+00  8.64e-07  1.27e-06  4.02e-07  7.63e-06  4.16e-06  9.40e-01
+  9   5.6923e+00   5.6923e+00  1.21e-08  1.76e-08  5.58e-09  1.06e-07  5.77e-08  9.87e-01
+ 10   5.6923e+00   5.6923e+00  2.66e-10  3.80e-10  1.21e-10  2.33e-09  1.25e-09  9.78e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 5.05ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -5.69231e+00
+  Dual objective value : -5.69231e+00
+
+* Work counters
+  Solve time (sec)   : 5.04668e-03
+  Barrier iterations : 10

The third level improves it even further

model6 = solve(6)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 451
+  constraints   = 506
+  nnz(P)        = 0
+  nnz(A)        = 1376
+  cones (total) = 10
+    : Zero        = 1,  numel = 56
+    : PSDTriangle = 9,  numel = (55,55,10,55,...,55)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   6.2703e-01   6.2703e-01  0.00e+00  7.56e-01  5.36e-01  1.00e+00  1.48e+00   ------
+  1   7.4953e-01   7.6135e-01  1.18e-02  1.58e-01  9.97e-02  2.39e-01  4.26e-01  8.06e-01
+  2   1.2333e+00   1.3121e+00  6.39e-02  4.31e-02  2.64e-02  1.73e-01  1.70e-01  8.68e-01
+  3   1.9671e+00   2.0062e+00  1.99e-02  1.22e-02  4.68e-03  6.32e-02  3.87e-02  8.18e-01
+  4   2.7047e+00   2.7536e+00  1.81e-02  8.45e-03  2.26e-03  6.99e-02  1.94e-02  7.43e-01
+  5   3.0495e+00   3.0614e+00  3.90e-03  3.75e-03  9.47e-04  2.13e-02  8.43e-03  9.22e-01
+  6   3.4706e+00   3.4774e+00  1.96e-03  9.59e-04  2.24e-04  9.63e-03  1.95e-03  8.04e-01
+  7   3.7081e+00   3.7129e+00  1.30e-03  4.91e-04  1.15e-04  6.51e-03  9.26e-04  6.34e-01
+  8   3.9158e+00   3.9173e+00  3.71e-04  1.29e-04  3.04e-05  1.93e-03  2.38e-04  8.24e-01
+  9   3.9469e+00   3.9488e+00  4.92e-04  8.66e-05  1.55e-05  2.34e-03  1.30e-04  6.86e-01
+ 10   4.0073e+00   4.0086e+00  3.31e-04  3.98e-05  5.09e-06  1.52e-03  4.86e-05  7.76e-01
+ 11   4.0267e+00   4.0275e+00  1.76e-04  1.93e-05  2.66e-06  8.15e-04  2.55e-05  7.35e-01
+ 12   4.0582e+00   4.0584e+00  3.91e-05  3.52e-06  4.53e-07  1.79e-04  4.47e-06  9.70e-01
+ 13   4.0660e+00   4.0660e+00  1.14e-05  9.59e-07  1.23e-07  5.20e-05  1.22e-06  8.03e-01
+ 14   4.0671e+00   4.0671e+00  6.05e-06  4.79e-07  6.23e-08  2.75e-05  6.16e-07  6.69e-01
+ 15   4.0683e+00   4.0683e+00  7.91e-07  6.17e-08  8.06e-09  3.60e-06  7.98e-08  8.78e-01
+ 16   4.0684e+00   4.0684e+00  3.27e-07  2.44e-08  3.20e-09  1.48e-06  3.17e-08  7.67e-01
+ 17   4.0685e+00   4.0685e+00  6.90e-09  5.14e-10  6.73e-11  3.12e-08  6.67e-10  9.80e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 46.5ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -4.06848e+00
+  Dual objective value : -4.06848e+00
+
+* Work counters
+  Solve time (sec)   : 4.64521e-02
+  Barrier iterations : 17

The fourth level finds the optimal objective value as lower bound.

model8 = solve(8)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 1813
+  constraints   = 1938
+  nnz(P)        = 0
+  nnz(A)        = 5689
+  cones (total) = 10
+    : Zero        = 1,  numel = 126
+    : PSDTriangle = 9,  numel = (210,210,66,210,...,276)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   5.6617e-01   5.6617e-01  4.44e-16  8.17e-01  7.34e-01  1.00e+00  1.32e+00   ------
+  1   6.4674e-01   6.4734e-01  6.01e-04  1.62e-01  1.39e-01  2.54e-01  4.12e-01  7.90e-01
+  2   8.6375e-01   9.4985e-01  8.61e-02  6.23e-02  5.34e-02  2.30e-01  2.32e-01  7.49e-01
+  3   1.3638e+00   1.3968e+00  2.41e-02  1.40e-02  8.73e-03  6.36e-02  5.21e-02  9.26e-01
+  4   2.0678e+00   2.0994e+00  1.53e-02  5.77e-03  2.46e-03  4.79e-02  1.82e-02  7.97e-01
+  5   2.3355e+00   2.3550e+00  8.36e-03  3.83e-03  1.37e-03  3.02e-02  1.09e-02  5.39e-01
+  6   2.7753e+00   2.7885e+00  4.75e-03  1.63e-03  4.62e-04  1.85e-02  4.07e-03  7.19e-01
+  7   3.1431e+00   3.1447e+00  5.16e-04  5.25e-04  1.36e-04  3.42e-03  1.30e-03  9.52e-01
+  8   3.2519e+00   3.2544e+00  7.58e-04  3.30e-04  8.17e-05  3.94e-03  7.58e-04  6.30e-01
+  9   3.3335e+00   3.3356e+00  6.53e-04  2.40e-04  5.77e-05  3.31e-03  5.40e-04  5.27e-01
+ 10   3.5632e+00   3.5650e+00  5.04e-04  7.97e-05  1.71e-05  2.29e-03  1.62e-04  7.81e-01
+ 11   3.6267e+00   3.6288e+00  5.82e-04  6.38e-05  1.32e-05  2.58e-03  1.22e-04  4.53e-01
+ 12   3.8605e+00   3.8614e+00  2.08e-04  2.21e-05  4.24e-06  9.82e-04  4.09e-05  7.15e-01
+ 13   3.9773e+00   3.9775e+00  2.96e-05  3.42e-06  6.21e-07  1.45e-04  6.28e-06  8.75e-01
+ 14   3.9966e+00   3.9967e+00  5.04e-06  4.70e-07  8.32e-08  2.39e-05  8.76e-07  9.42e-01
+ 15   3.9996e+00   3.9996e+00  6.22e-07  5.44e-08  9.54e-09  2.92e-06  1.02e-07  9.37e-01
+ 16   4.0000e+00   4.0000e+00  5.81e-08  5.04e-09  8.81e-10  2.72e-07  9.45e-09  9.08e-01
+ 17   4.0000e+00   4.0000e+00  1.74e-08  1.45e-09  2.52e-10  8.10e-08  2.71e-09  8.55e-01
+ 18   4.0000e+00   4.0000e+00  2.70e-09  3.35e-10  3.91e-11  1.26e-08  4.19e-10  8.51e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time =  840ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -4.00000e+00
+  Dual objective value : -4.00000e+00
+
+* Work counters
+  Solve time (sec)   : 8.39989e-01
+  Barrier iterations : 18

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/goldstein_price.ipynb b/previews/PR347/generated/Polynomial Optimization/goldstein_price.ipynb new file mode 100644 index 000000000..8cc8adbac --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/goldstein_price.ipynb @@ -0,0 +1,429 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Goldstein-price function" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "In this example, we consider the minimization of the [Goldstein-price function](https://en.wikipedia.org/wiki/Test_functions_for_optimization)." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "using DynamicPolynomials" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "Create *symbolic* variables (not JuMP *decision* variables)" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂],)" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "@polyvar x[1:2]" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "To use Sum-of-Squares Programming, we first need to pick an SDP solver,\n", + "see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "A JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: EMPTY_OPTIMIZER\nSolver name: Dual model with Clarabel attached" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "import Clarabel\n", + "using Dualization\n", + "model = SOSModel(dual_optimizer(Clarabel.Optimizer))" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Create a JuMP decision variable for the lower bound" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "γ", + "text/latex": "$ γ $" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "@variable(model, γ)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "`f(x)` is the Goldstein-Price function" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "600 + 720x₂ + 720x₁ + 3060x₂² - 4680x₁x₂ + 1260x₁² + 12288x₂³ - 19296x₁x₂² + 7344x₁²x₂ - 1072x₁³ + 14346x₂⁴ - 23616x₁x₂³ + 7776x₁²x₂² + 5784x₁³x₂ - 2454x₁⁴ + 1944x₂⁵ - 11880x₁x₂⁴ + 5040x₁²x₂³ + 9840x₁³x₂² - 7680x₁⁴x₂ + 1344x₁⁵ - 4428x₂⁶ - 1188x₁x₂⁵ + 8730x₁²x₂⁴ + 1240x₁³x₂³ - 5370x₁⁴x₂² - 168x₁⁵x₂ + 952x₁⁶ - 648x₂⁷ + 1944x₁x₂⁶ + 3672x₁²x₂⁵ - 3480x₁³x₂⁴ - 4080x₁⁴x₂³ + 2592x₁⁵x₂² + 1344x₁⁶x₂ - 768x₁⁷ + 729x₂⁸ + 972x₁x₂⁷ - 1458x₁²x₂⁶ - 1836x₁³x₂⁵ + 1305x₁⁴x₂⁴ + 1224x₁⁵x₂³ - 648x₁⁶x₂² - 288x₁⁷x₂ + 144x₁⁸", + "text/latex": "$$ 600 + 720x_{2} + 720x_{1} + 3060x_{2}^{2} - 4680x_{1}x_{2} + 1260x_{1}^{2} + 12288x_{2}^{3} - 19296x_{1}x_{2}^{2} + 7344x_{1}^{2}x_{2} - 1072x_{1}^{3} + 14346x_{2}^{4} - 23616x_{1}x_{2}^{3} + 7776x_{1}^{2}x_{2}^{2} + 5784x_{1}^{3}x_{2} - 2454x_{1}^{4} + 1944x_{2}^{5} - 11880x_{1}x_{2}^{4} + 5040x_{1}^{2}x_{2}^{3} + 9840x_{1}^{3}x_{2}^{2} - 7680x_{1}^{4}x_{2} + 1344x_{1}^{5} - 4428x_{2}^{6} - 1188x_{1}x_{2}^{5} + 8730x_{1}^{2}x_{2}^{4} + 1240x_{1}^{3}x_{2}^{3} - 5370x_{1}^{4}x_{2}^{2} - 168x_{1}^{5}x_{2} + 952x_{1}^{6} - 648x_{2}^{7} + 1944x_{1}x_{2}^{6} + 3672x_{1}^{2}x_{2}^{5} - 3480x_{1}^{3}x_{2}^{4} - 4080x_{1}^{4}x_{2}^{3} + 2592x_{1}^{5}x_{2}^{2} + 1344x_{1}^{6}x_{2} - 768x_{1}^{7} + 729x_{2}^{8} + 972x_{1}x_{2}^{7} - 1458x_{1}^{2}x_{2}^{6} - 1836x_{1}^{3}x_{2}^{5} + 1305x_{1}^{4}x_{2}^{4} + 1224x_{1}^{5}x_{2}^{3} - 648x_{1}^{6}x_{2}^{2} - 288x_{1}^{7}x_{2} + 144x_{1}^{8} $$" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "f1 = x[1] + x[2] + 1\n", + "f2 = 19 - 14*x[1] + 3*x[1]^2 - 14*x[2] + 6*x[1]*x[2] + 3*x[2]^2\n", + "f3 = 2*x[1] - 3*x[2]\n", + "f4 = 18 - 32*x[1] + 12*x[1]^2 + 48*x[2] - 36*x[1]*x[2] + 27*x[2]^2\n", + "f = (1 + f1^2*f2) * (30 + f3^2*f4)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Constraints `f(x) - γ` to be a sum of squares" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 45\n", + " constraints = 121\n", + " nnz(P) = 0\n", + " nnz(A) = 121\n", + " cones (total) = 2\n", + " : Zero = 1, numel = 1\n", + " : PSDTriangle = 1, numel = 120\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 6.0000e+02 6.0000e+02 0.00e+00 6.51e-01 4.57e-01 1.00e+00 1.02e+04 ------ \n", + " 1 -3.0355e+03 -2.4055e+03 2.62e-01 1.69e-01 1.33e-01 6.30e+02 2.58e+03 8.06e-01 \n", + " 2 -4.5486e+02 -2.1780e+02 1.09e+00 2.38e-02 2.39e-02 2.37e+02 5.36e+02 8.67e-01 \n", + " 3 3.2891e+01 7.6205e+01 1.32e+00 3.59e-03 3.47e-03 4.33e+01 9.46e+01 8.76e-01 \n", + " 4 2.7894e+01 3.5220e+01 2.63e-01 6.65e-04 6.22e-04 7.33e+00 1.84e+01 8.59e-01 \n", + " 5 1.2781e+01 1.9102e+01 4.95e-01 3.55e-04 4.58e-04 6.32e+00 1.16e+01 5.36e-01 \n", + " 6 5.6656e+00 6.5505e+00 1.56e-01 5.37e-05 7.07e-05 8.85e-01 1.88e+00 8.72e-01 \n", + " 7 4.1810e+00 4.5446e+00 8.70e-02 1.90e-05 2.68e-05 3.64e-01 6.80e-01 8.09e-01 \n", + " 8 3.4403e+00 3.5519e+00 3.24e-02 6.41e-06 8.82e-06 1.12e-01 2.39e-01 7.54e-01 \n", + " 9 3.0919e+00 3.1106e+00 6.05e-03 1.22e-06 1.64e-06 1.87e-02 4.73e-02 9.05e-01 \n", + " 10 3.0407e+00 3.0532e+00 4.11e-03 6.93e-07 8.40e-07 1.25e-02 2.76e-02 7.30e-01 \n", + " 11 3.0066e+00 3.0087e+00 7.02e-04 2.93e-07 1.38e-07 2.11e-03 4.66e-03 8.53e-01 \n", + " 12 3.0030e+00 3.0039e+00 2.96e-04 3.58e-07 6.00e-08 8.88e-04 2.02e-03 6.77e-01 \n", + " 13 3.0030e+00 3.0040e+00 3.29e-04 8.15e-07 6.27e-08 9.87e-04 1.79e-03 1.89e-03 \n", + " 14 3.0029e+00 3.0039e+00 3.06e-04 2.51e-06 5.98e-08 9.20e-04 1.71e-03 8.88e-02 \n", + " 15 3.0007e+00 3.0009e+00 6.28e-05 5.60e-07 1.35e-08 1.88e-04 3.96e-04 9.18e-01 \n", + " 16 3.0002e+00 3.0002e+00 1.46e-05 1.34e-07 3.15e-09 4.37e-05 9.44e-05 8.28e-01 \n", + " 17 3.0000e+00 3.0001e+00 4.04e-06 3.90e-08 8.72e-10 1.21e-05 2.71e-05 8.35e-01 \n", + " 18 3.0000e+00 3.0001e+00 4.04e-06 3.90e-08 8.72e-10 1.21e-05 2.71e-05 0.00e+00 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved (reduced accuracy)\n", + "solve time = 30.0ms\n" + ] + } + ], + "cell_type": "code", + "source": [ + "con_ref = @constraint(model, f >= γ)\n", + "@objective(model, Max, γ)\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "The lower bound found is 3" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Dual model with Clarabel attached\n\n* Status\n Result count : 1\n Termination status : ALMOST_OPTIMAL\n Message from the solver:\n \"ALMOST_SOLVED\"\n\n* Candidate solution (result #1)\n Primal status : NEARLY_FEASIBLE_POINT\n Dual status : NEARLY_FEASIBLE_POINT\n Objective value : 3.00006e+00\n Dual objective value : 3.00005e+00\n\n* Work counters\n Solve time (sec) : 2.99624e-02\n Barrier iterations : 18\n" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "The moment matrix is as follows, we can already see the global minimizer\n", + "`[0, -1]` from the entries `(2, 1)` and `(3, 1)`.\n", + "This heuristic way to obtain solutions to the polynomial optimization problem\n", + "is suggested in [Laurent2008; (6.15)](@cite)." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MomentMatrix with row/column basis:\n MonomialBasis([1, x[2], x[1], x[2]^2, x[1]*x[2], x[1]^2, x[2]^3, x[1]*x[2]^2, x[1]^2*x[2], x[1]^3, x[2]^4, x[1]*x[2]^3, x[1]^2*x[2]^2, x[1]^3*x[2], x[1]^4])\nAnd entries in a 15×15 SymMatrix{Float64}:\n 1.0000000018573474 -0.999998184576739 … 3.5962086853253903e-6\n -0.999998184576739 0.999997150198852 1.0531832701061796e-6\n -1.2636567926751192e-6 1.4804132265158204e-6 6.267497079311888e-6\n 0.9999971886457574 -0.9999960645215564 0.00021144386295502015\n 1.4653553927555777e-6 -1.1547395566676937e-6 0.00021277355946083603\n 1.187350682495253e-6 1.605777819548949e-7 … 0.0004346101519721536\n -0.9999960345776464 0.9999952039300222 -0.00037037588687171245\n -1.1433741839080068e-6 1.273723901361668e-6 -0.00041077802563794515\n 1.5687335193614228e-7 3.467245543475798e-7 -0.00022841391643848772\n 1.2660969071438837e-6 8.152487714237158e-7 -6.123905166790361e-5\n 0.9999951935941798 -0.9999943253292334 … 0.39570337503546366\n 1.271793213373499e-6 -1.3109438435614527e-6 -0.0010509740296115082\n 3.573504479057564e-7 -1.926462192043419e-7 0.5917596920647119\n 8.265186088348277e-7 6.000631118417262e-8 0.2928164690573049\n 3.5962086853253903e-6 1.0531832701061796e-6 1.0338233525191614" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "ν = moment_matrix(con_ref)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "Many entries of the matrix actually have the same moment.\n", + "We can obtain the following list of these moments without duplicates\n", + "(ignoring when difference of entries representing the same moments is below `1e-5`)" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Measure{Float64, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}([1.0000000018573474, -0.999998184576739, -1.2636567926751192e-6, 0.9999971886457574, 1.4653553927555777e-6, 1.187350682495253e-6, -0.9999960345776464, -1.1433741839080068e-6, 1.5687335193614228e-7, 1.2660969071438837e-6 … -6.123905166790361e-5, 1.270218769208648, -0.19058213646104005, 0.3086716525700899, -0.1318706321712997, 0.39570337503546366, -0.0010509740296115082, 0.5917596920647119, 0.2928164690573049, 1.0338233525191614], DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[1, x₂, x₁, x₂², x₁x₂, x₁², x₂³, x₁x₂², x₁²x₂, x₁³ … x₁⁷, x₂⁸, x₁x₂⁷, x₁²x₂⁶, x₁³x₂⁵, x₁⁴x₂⁴, x₁⁵x₂³, x₁⁶x₂², x₁⁷x₂, x₁⁸])" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "μ = measure(ν, atol = 1e-5)" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "The truncated moment matrix can then be obtained as follows" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MomentMatrix with row/column basis:\n MonomialBasis([1, x[2], x[1], x[2]^2, x[1]*x[2], x[1]^2, x[2]^3, x[1]*x[2]^2, x[1]^2*x[2], x[1]^3])\nAnd entries in a 10×10 SymMatrix{Float64}:\n 1.0000000018573474 -0.999998184576739 … 1.2660969071438837e-6\n -0.999998184576739 0.9999971886457574 8.265186088348277e-7\n -1.2636567926751192e-6 1.4653553927555777e-6 3.5962086853253903e-6\n 0.9999971886457574 -0.9999960345776464 6.000631118417262e-8\n 1.4653553927555777e-6 -1.1433741839080068e-6 1.0531832701061796e-6\n 1.187350682495253e-6 1.5687335193614228e-7 … 6.267497079311888e-6\n -0.9999960345776464 0.9999951935941798 7.041812532662351e-5\n -1.1433741839080068e-6 1.271793213373499e-6 0.00021144386295502015\n 1.5687335193614228e-7 3.573504479057564e-7 0.00021277355946083603\n 1.2660969071438837e-6 8.265186088348277e-7 0.0004346101519721536" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "ν_truncated = moment_matrix(μ, monomials(x, 0:3))" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "Let's check if the flatness property is satisfied.\n", + "The rank of `ν_truncated` seems to be 1:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "10-element Vector{Float64}:\n 4.00000395428376\n 0.0006683576478051575\n 0.00014945001542051055\n 7.258309877015935e-6\n 1.071254118692619e-6\n 3.7538602161096565e-7\n 2.1120262864418662e-7\n 9.941920943259009e-8\n 5.673286879095673e-8\n 2.160730842419555e-8" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra\n", + "LinearAlgebra.svdvals(Matrix(ν_truncated.Q))\n", + "LinearAlgebra.rank(Matrix(ν_truncated.Q), rtol = 1e-3)\n", + "svdvals(Matrix(ν_truncated.Q))" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "The rank of `ν` is clearly higher than 1, closer to 3:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "15-element Vector{Float64}:\n 5.074213473438938\n 1.5645319761479553\n 0.9597359871679573\n 0.0017398146185114327\n 0.0005408264077238202\n 0.00012333305842220714\n 0.000112117003942734\n 8.344767987724291e-6\n 1.1444727519464206e-6\n 3.1620324683887253e-7\n 1.486674010879845e-7\n 7.588328515192136e-8\n 1.2493207229285292e-8\n 4.7632154656602895e-9\n 4.013154592036812e-10" + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "svdvals(Matrix(ν.Q))" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "Even if the flatness property is not satisfied, we can\n", + "still try extracting the minimizer with a low rank decomposition of rank 3.\n", + "We find the optimal solution again doing so:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Atomic measure on the variables x[1], x[2] with 1 atoms:\n at [-1.1555204794988076e-6, -0.9999987643852531] with weight 1.0180428801820578" + }, + "metadata": {}, + "execution_count": 13 + } + ], + "cell_type": "code", + "source": [ + "atomic_measure(ν, FixedRank(3))" + ], + "metadata": {}, + "execution_count": 13 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/goldstein_price.jl b/previews/PR347/generated/Polynomial Optimization/goldstein_price.jl new file mode 100644 index 000000000..5152c36ed --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/goldstein_price.jl @@ -0,0 +1,39 @@ +using SumOfSquares +using DynamicPolynomials + +@polyvar x[1:2] + +import Clarabel +using Dualization +model = SOSModel(dual_optimizer(Clarabel.Optimizer)) + +@variable(model, γ) + +f1 = x[1] + x[2] + 1 +f2 = 19 - 14*x[1] + 3*x[1]^2 - 14*x[2] + 6*x[1]*x[2] + 3*x[2]^2 +f3 = 2*x[1] - 3*x[2] +f4 = 18 - 32*x[1] + 12*x[1]^2 + 48*x[2] - 36*x[1]*x[2] + 27*x[2]^2 +f = (1 + f1^2*f2) * (30 + f3^2*f4) + +con_ref = @constraint(model, f >= γ) +@objective(model, Max, γ) +optimize!(model) + +solution_summary(model) + +ν = moment_matrix(con_ref) + +μ = measure(ν, atol = 1e-5) + +ν_truncated = moment_matrix(μ, monomials(x, 0:3)) + +using LinearAlgebra +LinearAlgebra.svdvals(Matrix(ν_truncated.Q)) +LinearAlgebra.rank(Matrix(ν_truncated.Q), rtol = 1e-3) +svdvals(Matrix(ν_truncated.Q)) + +svdvals(Matrix(ν.Q)) + +atomic_measure(ν, FixedRank(3)) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/goldstein_price/index.html b/previews/PR347/generated/Polynomial Optimization/goldstein_price/index.html new file mode 100644 index 000000000..97810e9dd --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/goldstein_price/index.html @@ -0,0 +1,140 @@ + +Goldstein-price function · SumOfSquares

Goldstein-price function

Contributed by: Benoît Legat

In this example, we consider the minimization of the Goldstein-price function.

using SumOfSquares
+using DynamicPolynomials

Create symbolic variables (not JuMP decision variables)

@polyvar x[1:2]
(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂],)

To use Sum-of-Squares Programming, we first need to pick an SDP solver, see here for a list of the available choices.

import Clarabel
+using Dualization
+model = SOSModel(dual_optimizer(Clarabel.Optimizer))
A JuMP Model
+Feasibility problem with:
+Variables: 0
+Model mode: AUTOMATIC
+CachingOptimizer state: EMPTY_OPTIMIZER
+Solver name: Dual model with Clarabel attached

Create a JuMP decision variable for the lower bound

@variable(model, γ)

\[ γ \]

f(x) is the Goldstein-Price function

f1 = x[1] + x[2] + 1
+f2 = 19 - 14*x[1] + 3*x[1]^2 - 14*x[2] + 6*x[1]*x[2] + 3*x[2]^2
+f3 = 2*x[1] - 3*x[2]
+f4 = 18 - 32*x[1] + 12*x[1]^2 + 48*x[2] - 36*x[1]*x[2] + 27*x[2]^2
+f = (1 + f1^2*f2) * (30 + f3^2*f4)

\[ 600 + 720x_{2} + 720x_{1} + 3060x_{2}^{2} - 4680x_{1}x_{2} + 1260x_{1}^{2} + 12288x_{2}^{3} - 19296x_{1}x_{2}^{2} + 7344x_{1}^{2}x_{2} - 1072x_{1}^{3} + 14346x_{2}^{4} - 23616x_{1}x_{2}^{3} + 7776x_{1}^{2}x_{2}^{2} + 5784x_{1}^{3}x_{2} - 2454x_{1}^{4} + 1944x_{2}^{5} - 11880x_{1}x_{2}^{4} + 5040x_{1}^{2}x_{2}^{3} + 9840x_{1}^{3}x_{2}^{2} - 7680x_{1}^{4}x_{2} + 1344x_{1}^{5} - 4428x_{2}^{6} - 1188x_{1}x_{2}^{5} + 8730x_{1}^{2}x_{2}^{4} + 1240x_{1}^{3}x_{2}^{3} - 5370x_{1}^{4}x_{2}^{2} - 168x_{1}^{5}x_{2} + 952x_{1}^{6} - 648x_{2}^{7} + 1944x_{1}x_{2}^{6} + 3672x_{1}^{2}x_{2}^{5} - 3480x_{1}^{3}x_{2}^{4} - 4080x_{1}^{4}x_{2}^{3} + 2592x_{1}^{5}x_{2}^{2} + 1344x_{1}^{6}x_{2} - 768x_{1}^{7} + 729x_{2}^{8} + 972x_{1}x_{2}^{7} - 1458x_{1}^{2}x_{2}^{6} - 1836x_{1}^{3}x_{2}^{5} + 1305x_{1}^{4}x_{2}^{4} + 1224x_{1}^{5}x_{2}^{3} - 648x_{1}^{6}x_{2}^{2} - 288x_{1}^{7}x_{2} + 144x_{1}^{8} \]

Constraints f(x) - γ to be a sum of squares

con_ref = @constraint(model, f >= γ)
+@objective(model, Max, γ)
+optimize!(model)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 45
+  constraints   = 121
+  nnz(P)        = 0
+  nnz(A)        = 121
+  cones (total) = 2
+    : Zero        = 1,  numel = 1
+    : PSDTriangle = 1,  numel = 120
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   6.0000e+02   6.0000e+02  0.00e+00  6.51e-01  4.57e-01  1.00e+00  1.02e+04   ------
+  1  -3.0355e+03  -2.4055e+03  2.62e-01  1.69e-01  1.33e-01  6.30e+02  2.58e+03  8.06e-01
+  2  -4.5486e+02  -2.1780e+02  1.09e+00  2.38e-02  2.39e-02  2.37e+02  5.36e+02  8.67e-01
+  3   3.2891e+01   7.6205e+01  1.32e+00  3.59e-03  3.47e-03  4.33e+01  9.46e+01  8.76e-01
+  4   2.7894e+01   3.5220e+01  2.63e-01  6.65e-04  6.22e-04  7.33e+00  1.84e+01  8.59e-01
+  5   1.2781e+01   1.9102e+01  4.95e-01  3.55e-04  4.58e-04  6.32e+00  1.16e+01  5.36e-01
+  6   5.6656e+00   6.5505e+00  1.56e-01  5.37e-05  7.07e-05  8.85e-01  1.88e+00  8.72e-01
+  7   4.1810e+00   4.5446e+00  8.70e-02  1.90e-05  2.68e-05  3.64e-01  6.80e-01  8.09e-01
+  8   3.4403e+00   3.5519e+00  3.24e-02  6.41e-06  8.82e-06  1.12e-01  2.39e-01  7.54e-01
+  9   3.0919e+00   3.1106e+00  6.05e-03  1.22e-06  1.64e-06  1.87e-02  4.73e-02  9.05e-01
+ 10   3.0407e+00   3.0532e+00  4.11e-03  6.93e-07  8.40e-07  1.25e-02  2.76e-02  7.30e-01
+ 11   3.0066e+00   3.0087e+00  7.02e-04  2.93e-07  1.38e-07  2.11e-03  4.66e-03  8.53e-01
+ 12   3.0030e+00   3.0039e+00  2.96e-04  3.58e-07  6.00e-08  8.88e-04  2.02e-03  6.77e-01
+ 13   3.0030e+00   3.0040e+00  3.29e-04  8.15e-07  6.27e-08  9.87e-04  1.79e-03  1.89e-03
+ 14   3.0029e+00   3.0039e+00  3.06e-04  2.51e-06  5.98e-08  9.20e-04  1.71e-03  8.88e-02
+ 15   3.0007e+00   3.0009e+00  6.28e-05  5.60e-07  1.35e-08  1.88e-04  3.96e-04  9.18e-01
+ 16   3.0002e+00   3.0002e+00  1.46e-05  1.34e-07  3.15e-09  4.37e-05  9.44e-05  8.28e-01
+ 17   3.0000e+00   3.0001e+00  4.04e-06  3.90e-08  8.72e-10  1.21e-05  2.71e-05  8.35e-01
+ 18   3.0000e+00   3.0001e+00  4.04e-06  3.90e-08  8.72e-10  1.21e-05  2.71e-05  0.00e+00
+---------------------------------------------------------------------------------------------
+Terminated with status = solved (reduced accuracy)
+solve time = 18.1ms

The lower bound found is 3

solution_summary(model)
* Solver : Dual model with Clarabel attached
+
+* Status
+  Result count       : 1
+  Termination status : ALMOST_OPTIMAL
+  Message from the solver:
+  "ALMOST_SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : NEARLY_FEASIBLE_POINT
+  Dual status        : NEARLY_FEASIBLE_POINT
+  Objective value    : 3.00006e+00
+  Dual objective value : 3.00005e+00
+
+* Work counters
+  Solve time (sec)   : 1.80730e-02
+  Barrier iterations : 18
+

The moment matrix is as follows, we can already see the global minimizer [0, -1] from the entries (2, 1) and (3, 1). This heuristic way to obtain solutions to the polynomial optimization problem is suggested in (Laurent, 2008; (6.15)).

ν = moment_matrix(con_ref)
MomentMatrix with row/column basis:
+ MonomialBasis([1, x[2], x[1], x[2]^2, x[1]*x[2], x[1]^2, x[2]^3, x[1]*x[2]^2, x[1]^2*x[2], x[1]^3, x[2]^4, x[1]*x[2]^3, x[1]^2*x[2]^2, x[1]^3*x[2], x[1]^4])
+And entries in a 15×15 SymMatrix{Float64}:
+  1.0000000018573474     -0.999998184576739      …   3.5962086853253903e-6
+ -0.999998184576739       0.999997150198852          1.0531832701061796e-6
+ -1.2636567926751192e-6   1.4804132265158204e-6      6.267497079311888e-6
+  0.9999971886457574     -0.9999960645215564         0.00021144386295502015
+  1.4653553927555777e-6  -1.1547395566676937e-6      0.00021277355946083603
+  1.187350682495253e-6    1.605777819548949e-7   …   0.0004346101519721536
+ -0.9999960345776464      0.9999952039300222        -0.00037037588687171245
+ -1.1433741839080068e-6   1.273723901361668e-6      -0.00041077802563794515
+  1.5687335193614228e-7   3.467245543475798e-7      -0.00022841391643848772
+  1.2660969071438837e-6   8.152487714237158e-7      -6.123905166790361e-5
+  0.9999951935941798     -0.9999943253292334     …   0.39570337503546366
+  1.271793213373499e-6   -1.3109438435614527e-6     -0.0010509740296115082
+  3.573504479057564e-7   -1.926462192043419e-7       0.5917596920647119
+  8.265186088348277e-7    6.000631118417262e-8       0.2928164690573049
+  3.5962086853253903e-6   1.0531832701061796e-6      1.0338233525191614

Many entries of the matrix actually have the same moment. We can obtain the following list of these moments without duplicates (ignoring when difference of entries representing the same moments is below 1e-5)

μ = measure(ν, atol = 1e-5)
Measure{Float64, DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}([1.0000000018573474, -0.999998184576739, -1.2636567926751192e-6, 0.9999971886457574, 1.4653553927555777e-6, 1.187350682495253e-6, -0.9999960345776464, -1.1433741839080068e-6, 1.5687335193614228e-7, 1.2660969071438837e-6  …  -6.123905166790361e-5, 1.270218769208648, -0.19058213646104005, 0.3086716525700899, -0.1318706321712997, 0.39570337503546366, -0.0010509740296115082, 0.5917596920647119, 0.2928164690573049, 1.0338233525191614], DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[1, x₂, x₁, x₂², x₁x₂, x₁², x₂³, x₁x₂², x₁²x₂, x₁³  …  x₁⁷, x₂⁸, x₁x₂⁷, x₁²x₂⁶, x₁³x₂⁵, x₁⁴x₂⁴, x₁⁵x₂³, x₁⁶x₂², x₁⁷x₂, x₁⁸])

The truncated moment matrix can then be obtained as follows

ν_truncated = moment_matrix(μ, monomials(x, 0:3))
MomentMatrix with row/column basis:
+ MonomialBasis([1, x[2], x[1], x[2]^2, x[1]*x[2], x[1]^2, x[2]^3, x[1]*x[2]^2, x[1]^2*x[2], x[1]^3])
+And entries in a 10×10 SymMatrix{Float64}:
+  1.0000000018573474     -0.999998184576739      …  1.2660969071438837e-6
+ -0.999998184576739       0.9999971886457574        8.265186088348277e-7
+ -1.2636567926751192e-6   1.4653553927555777e-6     3.5962086853253903e-6
+  0.9999971886457574     -0.9999960345776464        6.000631118417262e-8
+  1.4653553927555777e-6  -1.1433741839080068e-6     1.0531832701061796e-6
+  1.187350682495253e-6    1.5687335193614228e-7  …  6.267497079311888e-6
+ -0.9999960345776464      0.9999951935941798        7.041812532662351e-5
+ -1.1433741839080068e-6   1.271793213373499e-6      0.00021144386295502015
+  1.5687335193614228e-7   3.573504479057564e-7      0.00021277355946083603
+  1.2660969071438837e-6   8.265186088348277e-7      0.0004346101519721536

Let's check if the flatness property is satisfied. The rank of ν_truncated seems to be 1:

using LinearAlgebra
+LinearAlgebra.svdvals(Matrix(ν_truncated.Q))
+LinearAlgebra.rank(Matrix(ν_truncated.Q), rtol = 1e-3)
+svdvals(Matrix(ν_truncated.Q))
10-element Vector{Float64}:
+ 4.00000395428376
+ 0.0006683576478051575
+ 0.00014945001542051055
+ 7.258309877015935e-6
+ 1.071254118692619e-6
+ 3.7538602161096565e-7
+ 2.1120262864418662e-7
+ 9.941920943259009e-8
+ 5.673286879095673e-8
+ 2.160730842419555e-8

The rank of ν is clearly higher than 1, closer to 3:

svdvals(Matrix(ν.Q))
15-element Vector{Float64}:
+ 5.074213473438938
+ 1.5645319761479553
+ 0.9597359871679573
+ 0.0017398146185114327
+ 0.0005408264077238202
+ 0.00012333305842220714
+ 0.000112117003942734
+ 8.344767987724291e-6
+ 1.1444727519464206e-6
+ 3.1620324683887253e-7
+ 1.486674010879845e-7
+ 7.588328515192136e-8
+ 1.2493207229285292e-8
+ 4.7632154656602895e-9
+ 4.013154592036812e-10

Even if the flatness property is not satisfied, we can still try extracting the minimizer with a low rank decomposition of rank 3. We find the optimal solution again doing so:

atomic_measure(ν, FixedRank(3))
Atomic measure on the variables x[1], x[2] with 1 atoms:
+ at [-1.1555204794988076e-6, -0.9999987643852531] with weight 1.0180428801820578

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/min_univariate.ipynb b/previews/PR347/generated/Polynomial Optimization/min_univariate.ipynb new file mode 100644 index 000000000..2b134078d --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/min_univariate.ipynb @@ -0,0 +1,715 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Maximizing as minimum" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: [Floudas1999; Section 4.10](@cite), [Laurent2008; Example 6.23](@cite) and [Lasserre2009; Table 5.1](@cite)" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the polynomial optimization problem from [Floudas1999; Section 4.10](@cite)\n", + "of minimizing the linear function $-x_1 - x_2$\n", + "over the basic semialgebraic set defined by the inequalities\n", + "$x_2 \\le 2x_1^4 - 8x_1^3 + 8x_1^2 + 2$,\n", + "$x_2 \\le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36$ and the box constraints\n", + "$0 \\le x_1 \\le 3$ and $0 \\le x_2 \\le 4$," + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Basic semialgebraic Set defined by no equality\n6 inequalities\n x[1] ≥ 0\n 3 - x[1] ≥ 0\n x[2] ≥ 0\n 4 - x[2] ≥ 0\n 2 - x[2] + 8*x[1]^2 - 8*x[1]^3 + 2*x[1]^4 ≥ 0\n 36 - x[2] - 96*x[1] + 88*x[1]^2 - 32*x[1]^3 + 4*x[1]^4 ≥ 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:2]\n", + "p = -sum(x)\n", + "using SumOfSquares\n", + "f1 = 2x[1]^4 - 8x[1]^3 + 8x[1]^2 + 2\n", + "f2 = 4x[1]^4 - 32x[1]^3 + 88x[1]^2 - 96x[1] + 36\n", + "K = @set x[1] >= 0 && x[1] <= 3 && x[2] >= 0 && x[2] <= 4 && x[2] <= f1 && x[2] <= f2" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "As we can observe below, the bounds on `x[2]` could be dropped and\n", + "optimization problem is equivalent to the maximization of `min(f1, f2)`\n", + "between `0` and `3`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=3}", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nO3deXwU9f0/8Pdndnf2TDabhEDui9wHl9yggIL1gKJVbLVq61Fb9Vtbq7WtPbxapT+/Vau21usr2nqfeB9FUUAEuRLISQIhCQmBJJtkN7s7uzOf3x8bEZQjgc3O7O7r+fDhI9lsdl8Jk33tZz6fmWGccwIAAIhVgtoBAAAA1IQiBACAmIYiBACAmIYiBACAmIYiBACAmIYiBACAmIYiBACAmIYiBACAmIYiBACAmIYiBACAmBamIqytrX3ssceGf/9AIDB6YSCC+P1+tSOAJmBLgKDR2BLCVIQ1NTXvv//+8O/v8/kURRm9PBApvF6v2hFAE7AlQNBobAnYNQoAADENRQgAADENRQgAADENRQgAADENRQgAADENRQgAADENRQgAADENRQgAADFNo0UYaKqS+7rVTgEAANFPo0UobV/v3bZG7RQAABD99GoHODJder7UWq92CgCAiLdhw4Z7771X7RQnizH217/+NTs7ezQeXKNFqE/L83z+ttopAAAi3rZt23p6eq655hq1g5yU22+/vbm5ObaKUBibGejZxyUvE01qZwEAiGx5eXkXXnih2ilOyj//+c/Re3CNzhEynd4wNsvf3qx2EAAAiHIaLUIi0mfkS2071U4BAABRTrtFKGaM96MIAQBglGm3CPUZ+VJro9opAAAgymm3CA1peYEDHdwvqR0EAACimXaLkOn0+pR0f8cutYMAAEA0024REpGYMR57RwEAolJdXd3cuXNzc3NffPHFvXv3Pvfcc7///e9XrFgR/iSaLkJDRoG/FetlAACi0PLly88888xdu3YtW7bsmWeeefrpp1evXv3KK6+EP4mmi1DMHC+1YUQIABBt3n777Y0bN+7evfvRRx91u9233HLLu+++u2TJElXCaLoIDWl5ga42HvCrHQQAAKKWRk+xFsQMoj4p1d+xW8wsUDsLAECU2OPiV30m8zA+48X5wo8LDxt3nXPOOQ899NCCBQsuvvjiMAY5Mk0XIRGJmQX+1kYUIQBAqKRa2C0TdDyMTVicEL7nOgFaL0JDxnipbadV7RgAAFHDINDpaUztFBqi6TlCGhoRYuEoAACMFq0XoSE937+vhcsBtYMAAMBoee211/Lz8++5557//ve/+fn5v/3tb8P57FrfNcpEoz5xbKCzxZCer3YWAAAImZdeekkUxeDH55xzzrx58w5+yWg0hjOJ1ouQiAyZBVLrThQhAEA0sdlsBz8WRfFgKYaf1neN0tD1mHBYPQAAjIoIKEJDZgGu0AsAAKMkAnaNiun5/r27uRxgughICwAAw1FdXf2jH/3I6XTefffdFovlzTff3LNnT2Zm5vXXX19ZWRnOJBEwImRGsy4hOdDVpnYQAAAImXvvvfeiiy5qampatmzZgw8+WFFR8ctf/nLcuHGzZ89uamoKZ5LIGGOJmQVSa6MhNUftIAAAEALPP//8+vXrJUlavnz5tdde+/777wdvX7Ro0UcfffTBBx/87Gc/C1uYCBgREpEhY7wf04QAANEiLi7OYDBYrVaHwyEIXzeRJEnBHaThDBMhI8Kswr5ta9ROAQAQDQI9+3qe+gtxJWzPaJ11tnXmWYfecrSTbt9yyy15eXlnn3122LJRxBRhZqG/A+tlAABCQJ8wxrHsf3gYz7qtd6QM527Lly9/7733Vq9efegYMQwio1eGzi/TsduQMV7tLAAAEU4QNPhaev/99z/++OOrV69OSRlWa4ZQZMwREpGYVSTtaVA7BQAAhN5jjz12//33f/jhh2lpaeF/9ggqwkJpT73aKQAAIPR+/vOfd3V1TZ48OTExMTEx8a677grns0fGrlEiErOLXGveVDsFAACExqEn3e7o6Dh0ztJkMoUzScQUoT41J9Czj/s8zGhWOwsAAJysQ0+6nZCg5jXsI2bXKNPpDak5UntYTzcAAABRL2KKkILThC2YJgQAgFCKrCIs8mPhKAAAhFREFWE2jqAAAIAQi6Qi1CenKZ4BxeVUOwgAAESPSCpCYsyQUSC14mr1AAAQMhFz+ESQmF0ktdSbSqaqHQQAIDLo9frXXntt8+bNagc5KQ0NDXr9aBVWpBVhVqH78/fUTgEAEDEuueSSMF/wfTSIolheXj5KDx5pRZhd3PvCA2qnAACIGKIoTpkyRe0UmhZRc4REuvhEptPLPV1qBwEAgCgRYUVIQ5ehwGH1AAAQGpFYhLgMBQAAhEzkFaEhqxCH1QMAQKhEXhGK2UX+tp2kKGoHAQCAaBB5RSiYrEKcw9/VqnYQAACIBpFXhDS0XgZ7RwEAIAQitAgL/VgvAwAAoRCZRZhdJLVgRAgAACEw3CK88sory8vLc3JyFi5cuHr16oO3v/rqq5MnT87Ly/vFL34hSdLohPwmQ3q+f98eLvnC83QAABDFhluECxYseOmll9atW7d06dKzzz67q6uLiBobG3/0ox/dfffdq1ev3rhx4z333DOaUb/GDKJhXLbUtjM8TwcAAFFsuEV4ySWXlJSUpKWlXXfddXq9vqmpiYiefPLJJUuWnHnmmZmZmbfddtsjjzwymlEPI+aWSLtrw/Z0AAAQrUZw0u3Gxsaurq6VK1cWFRUFT+G6Y8eOefPmBb86efLkjo6O3t5eh8MxGkG/Qcwu9mz9LAxPBAAA0W0ERfjkk0+uXr26oaHhzjvvFEWRiLq7u+Pj44NftdvtRLR///4jFmFzc/PKlSsP/dKKFSsWLFhwtOcaHByUZVkQjjpgVcZk+3b9y+VyDT8/RCK3280YUzsFqA9bAgSNdEuwWCzHqJKgERTh3XffTURtbW2TJ08uKipasGCBw+EYGBgIfrW/v5+IEhMTj/i9eXl53/nOd1asWHHwloSEhGP8MIwxs9l8rPQ2m1sQzNKgLjFl+D8CRBzOuc1mUzsFqA9bAgSNxpYw4sMnMjIyysvLa2pqiCg/P7+uri54e11dXUJCQlJS0tG+URRFxyFO/s2dmF3s211zkg8CAAAxblhF2NHRsX79elmWOefvvPPOhg0bZs+eTUSXXXbZyy+/vHPnzkAgcO+991522WXh3Hch5pRILXVhezoAAIhKwypCl8t1zTXXWK1Wm8120003Pf7445MmTSKiKVOm3HrrrdOmTUtKSvL7/Xfccccopz2MmFMi7cLCUQAAOCnDmiMsKCjYtm2boiiyLBsMhkO/dOONN954442SJAWXz4STmFng72zhfokZwv3UAAAQNUYwRygIwjda8KDwtyAFD6sfm+Vvawz/UwMAQNSIyHONHiTmlviwdxQAAE5ChBch1ssAAMDJifAizC7GidYAAOBkRHYR6pPGEVfk3i61gwAAQKSK7CIkIjG7xIdBIQAAnKjIL8KcEmk3pgkBAOAERUERYpoQAABOXOQXYVZR8LB6tYMAAEBEivgiZAbRkJLhb29SOwgAAESkiC9CIhJzsF4GAABOUHQUYTHOvg0AACcmOoqwRMKFCQEA4IREQxHqk1JJUWTnfrWDAABA5ImGIqTg2bebd6idAgAAIk/UFGGZhCIEAICRi5IiNOaX+3ahCAEAYMSipAjFjPFyd6ficakdBAAAIkyUFCEJOkNmIQ6iAACAkYqWIiQy5pVh7ygAAIxU9BShmIf1MgAAMGLRU4TGnBKpbSfOvg0AACMSPUXIjGZDSoa/rVHtIAAAEEmipwiJSMwrw2H1AAAwIlFVhMa8Ml8zTjoKAAAjEFVFKOaVS7t2EOdqBwEAgIgRVUWoi3MIljh/Z4vaQQAAIGJEVRESkREHUQAAwEhEWxGKeTjpKAAAjEC0FaExr8zXvF3tFAAAEDGirQj1Y9K5JOEivQAAMEzRVoTEmDGvFEcTAgDAMEVdEQYPokARAgDA8ERhEWKaEAAAhi8Ki1DMGC/37FMGB9QOAgAAESAKi5AEnSGrUNqNi/QCAMDxRWMREhnzyn1N2DsKAADHF6VFOH6Cr6lK7RQAABABorMIxZxif0cL93nUDgIAAFoXnUXI9AYxqxBHEwIAwHFFZxESkTG/wtdUrXYKAADQuugtwvETfDu3qZ0CAAC0LmqLENOEAAAwHFFbhJgmBACA4YjaIiRMEwIAwDBEdRFimhAAAI4nmosQ04QAAHBc0VyEmCYEAIDjiuYiJEwTAgDA8UR7EWKaEAAAjinKixDThAAAcGxRXoSYJgQAgGOL8iIkTBMCAMAxxUARYpoQAACOLvqLENOEAABwDNFfhJgmBACAY4j+IqTgNOHOKrVTAACAFsVGERZO9DVsVTsFAABoUUwUoZhdHNjfpgwOqB0EAAA0JyaKkOn0Yl6ZrxFrRwEA4JtiogiJyFg4yduwRe0UAACgObFShKbCSb56FCEAAHxTrBShITWHS55Ad6faQQAAQFtipQiJMWPBRF8j1o4CAMBhYqYIiYyFk3yYJgQAgMPFUBGaiqd467cQ52oHAQAADYmhItTZkwRrvL+9We0gAACgITFUhERkwkEUAABwuNgqQkwTAgDAN8RYERZU+nbV8IBf7SAAAKAVsVWEgtlmSM2WdtWoHQQAALQitoqQME0IAACHi7kiNOJcawAAcIiYK0IxtzTQ1YpLMgEAQFDMFSHT6cXcUlywHgAAgmKuCAkHUQAAwCFisQhNhZO8mCYEAAAiis0iNKTlcp8n0N2hdhAAAFBfLBYhMWYqnuKt3aR2DgAAUF9MFiGRseQUb+2XaqcAAAD1xWgRmoqmSE3VONcaAADEaBEKFps+NVtq3q52EAAAUFmMFiERmYqxdxQAAGK5CEtP8dZuVDsFAACoTD+cOwUCgVWrVn3yyScDAwMTJ0689NJLRVEMfqm1tfWRRx7p6+tbsmTJokWLRjNqiIkZBYp7QO7p0iWmqJ0FAABUM6wRYVVV1c0332w2m0tKSh555JHFixcHb3c6nTNmzHC5XBUVFZdeeunLL788mlFDjTFj8WRvHfaOAgDEtGGNCCsqKrZt2xb8+LzzzktLS2ttbc3MzHz66aeLiooeeOABIjKbzffcc88FF1wwimFDzVR8imfrZ9ZZZ6sdBAAAVDOsEaHBYDj48cDAgCAI8fHxRLR27drTTz89ePuCBQs2bdo0ODg4GilHial4im9nFZcDagcBAADVDGtEeJAsy9ddd931119vt9uJqKOjY8GCBcEvpaSkBG/Jz8//9jd2dHSsX7/+e9/7XvBTnU534403VlZWHu2JBgcHOeeCMMpreZheSE4bqN2szysf3SeCE+XxeHQ6ndopQH3YEoCIONFtW/gdpwyyYX+LyWQ6bpWMoAgVRbn66qs558uXLw/eIopiIDA0nJIkKfiUR/xeu92ekZGxbNmyg7fk5OQYjcajPVcgEDAajaNehETm0qlKc5WxZMpoPxGcGEmSjrGdQOzAlgBE9Eknvb9P91fjCJqLseOX5nAfjnN+3XXX7dy589133z3Ydunp6W1tbcGP29ra9Hp9cFz4bRaLJSMj46KLLhrm0+l0Op1OF54i7H3+/oQlV432E8GJCW4JaqcA9WFLACJ6okH+8Xgl5FvCsJqGc37DDTds3br17bfftlqtB29funTpa6+95vV6iei5554799xzD51NjAhiVpE80Cs796sdBAAAjqXbR++2Ksuy5JA/8rBGhGvXrn3wwQeLiormz58fvOXxxx+fOHHi4sWLH3nkkenTp+fn569du/bDDz8Meb5Rx5ipcJK3brN1xplqRwEAgKN6plFZnCUkiDzkjzysIpwwYcKXXx52vN348eOJSK/Xv/vuu+vWrevt7X3iiSccDkfI84WBqWSqZ/vnKEIAAC17vF755+xR2T0+rCKMi4ubMuXIy0kEQZgzZ05II4WbqeQU56v/5HKA6Ua2hhYAAMJj7T4eUGjOOOYaCP2Dx+65Rg8SbHb9mDRpV63aQQAA4Mgeq1OuLhaGf9TEiKAIiYhMZdO9O9arnQIAAI6gT6KVe5TLCkarsFCERETm8hme6s/VTgEAAEfwn53KonRhzJEPUw8BFCERkSE9nxQ5sK9V7SAAAPBNj9crVxePYluhCIeYSqd5dnyhdgoAADjMlwe4U6L5qaM0P0iEIjzIVD7Dux3ThAAA2hJcJjNa62SICEV4kLFggr9jt+LuVzsIAAAMcfnp5V3K5QWjWYMowoOYTm8snOSt2aB2EAAAGPJskzIvVUizoAjDxVw+3bMd04QAAFrxcI1yXemo9xSK8Gumsum+hi3cL6kdBAAA6LNO7ldoftroDgcJRXgowRJnSM3xNVWrHQQAAOjhGuXa0lFdJTMERXgYrB0FANCCjkH6sH0UzyZzKBThYczlMzzb1xMP/WU+AABg+B6tU76fL8SH5RK3KMLD6FMymEH0tzerHQQAIHYFFHq8XvnpaJ5N5lAowm8yV8z04ATcAADqea1FGR9PFYlhmB8kQhF+m6lsuhcHUQAAqCc8R00chCL8JmNuWaB3n+w8oHYQAIBYVOPkjX303WwUoYoEwVRyihcn4AYAUMNDO5RrSgRDGNsJRXgE5vKZnqq1aqcAAIg5A356oVm5sjBMs4NBKMIjMJVMlVrqcQJuAIAwW9GoLEwX0q0oQrUx0WgsmoTLEwIAhJPC6aEdys/Lwl1MKMIjM0+Y49m2Ru0UAAAxZOUeJc5As8aGdThIKMKjMZdNl5q2K1632kEAAGLFfdXKTZUqtBKK8MiY0Szml3t34PKEAADhsPkAbx6g83NQhFqCvaMAAGFz33blhvKwHjVxEIrwqMwVM30NW7nkVTsIAECU2zvI32lVripSp5JQhEclmG1iTrG3dqPaQQAAotxDO5RLC4QEUZ1nRxEei7lyNvaOAgCMqsEAPdGg/E8YTy76DSjCYzFPmOOt3cT9ktpBAACi1lMNypyxQn58uI+aOAhFeCyCNd6Qnutr2Kx2EACA6MSJHqxRflmuZhmhCI/DXDlncBvOOwoAMCre2qNY9TRnnGrDQUIRHpd5whzv9vVcDqgdBAAgCt1XrdxYoXIToQiPQ2dP0qdk+Bq3qR0EACDabNzPd/bThbkoQs3DkfUAAKPh7m3KryeocxD9odR+/khgmTDXU70Oe0cBAEKozsk/36dcUah+DamfQPt0iSn6Mem++i1qBwEAiB7Lq5Try3QWvdo5UITDZJk8b3Dzx2qnAACIEm1u/maLcm2JJjpIEyG0zzLpNG/NBi751A4CABAN7q1WriwSHEa1cxARinCYBJtdzCry1uCqTAAAJ6vHR/9uVG5Q9SD6Q2klh/aZsXcUACAUHtguX5ArpFnUPIj+UCjC4TJXzvY1Vikel9pBAAAimDtAj9Qpv1L7IPpDaSiKxgkmi7FggqdqndpBAAAi2L9qlfmpQoFdK8NBQhGOiGXKPM/mT9ROAQAQqSSF7tuu3DJBW9WjrTQaZyqdLrU2ygO9agcBAIhIT9YrExJpUpKGhoOEIhwRZhBNZdM8Wz9TOwgAQOTxK7S8SvnjZJ3aQb4JRTgylsnzBrF3FABg5B6vV8odNG2MtoaDhCIcKVPRZPlAR6C7U+0gAACRxK/QX6uUP0zS3HCQUIQjJujMlbM9W1arnQMAIJJodjhIKMITYJ6CvaMAACOg5eEgoQhPgDG3TPG6/Xt3qR0EACAyaHk4SCjCE8GY9ZTTBzd8qHYOAIAIoPHhIKEIT4xl2sLBTR/jUr0AAMel8eEgoQhPjD45TT8mzVv7pdpBAAA0TfvDQUIRnjDLtIXYOwoAcGz/qtP6cJBQhCfMPPFUX+M2xdWndhAAAI1y+ekvW+U7pmh6OEgowhMmmCymsmk4jgIA4Gj+tl05PU3Q2plFvw1FeOKs0xa6sXcUAOBIDnjpwR3ybZMjoGUiIKJmGQsmKu5+HFAIAPBtf9kqfz9PyI/X+nCQUIQnhTHr1NMHN36kdg4AAG1pd/Nndiq3anux6EEowpNimbZw8MtVOKAQAOBQf9ik/KxEGGdWO8fwoAhPSvCAQl8dDigEABhS38ffbVV+VREZw0FCEZ48y7SF7g3YOwoAMOQ3G5SbK3V2Ue0cw4YiPFnmiaf6GrYq7n61gwAAqG/Dfv7lAf6zkkgql0jKqk2CyWIqn44lMwAARHTTF/IdUwSzXu0cI4EiDAHrzLNdn79LnKsdBABATS/tUgb8dHlBhDVLhMXVJmNeGRN0vqbtagcBAFCNpNDvNir3TtcJEXDo4GFQhKFhnXmWe93baqcAAFDN36qVykR2elqk1SCKMFQs087w1n2puJxqBwEAUEGXh/5WLd8zNSI7JSJDa5BgsporZrm/wKlHASAW/X6T/KNCocAeecNBQhGGkHXW2e5172DJDADEmm09/M0W5daJEXME/TegCENGzC5mZquvcavaQQAAwurmL+TbpkTSEfTfgCIMJdvMs1xr31E7BQBA+LzRorS76crCCG6TCI6uQZZTFvgat8p93WoHAQAIB59MN29Q7p+p00dymURydu1hRrN54lz3hg/UDgIAEA5/rVIqE9nC9IhcI3MQijDEbLPPda97lxRF7SAAAKNrj4s/uEO+d1rE90jE/wBaY0jP08UleOs2qR0EAGB0Xb9OualSlxMX2cNBQhGOBuvsc11r3lQ7BQDAKHqjRWnq578sj4YSiYafQWssU+b723YG9rWqHQQAYFR4AvTL9cqDs3SGqOiQqPghNIbpDdaZ38GgEACi1V1b5Vlj2YIIPK3oEaEIR4Vt7pLBTR8rgwNqBwEACLHGPv5YnfLXyF8jc1D0/CSaItgSTGXT3OvfVzsIAECI/fxz+Q+TdGmWKBkOEopw9MSddp5rzUpSZLWDAACEzDM7lX0eurY0qrojqn4YTTFkjNcnpHiqP1c7CABAaBzw0i0b5Mfm6nTRMxokGlERut3urVu37t+//9AbFUVZu3btW2+95XTiUnzfZDttqWv162qnAAAIjWvXyj8uFKYkR1cNDr8Ily5dmpiYOH369BdffPHgjYFA4Jxzzrn22mufeOKJoqKi6urq0QkZqcwVs+S+A9KeBrWDAACcrLf28G09/A+TIvVaS8cw3CK84447uru758yZc+iNb731VnNz8xdffPHaa69dc801f/rTn0YhYSQTBOvsc12fvaF2DgCAk9In0bVr5cfn6kxR2IPDLsLKykqbzfaNG19//fXzzjvPZDIR0Q9+8IM333wzEAiEOGCEs878jnfHF7geBQBEtBvXy0tz2Nxx0bZTNEh/Mt/c1tY2derU4MdZWVmBQKCzszMjI+Pb9xwcHGxra3vhhRcO3nLaaaeNGTPmaI8sy7IsyzwKrvYums2T5rnWvm078xK1o0Sk4JagdgpQH7YEFX3SSf/dy7cuZVr4JxjpliAIAmPH6e+TKkJJkgwGQ/Dj4Ac+n++I9+zr62trazs4v6jT6bKzs+Pj44/2yD6fTxAEQYiGRa366d/p/9et+lmLmWhUO0vkkSTpaBsVxBRsCWoZDNBP1hgemCqLiqKFf4GRbgkmk2l0i3DcuHEHF5F2dXURUWpq6hHvmZqaOmPGjJdffnmYj8w5N5vN0VGElDVeyi/nVZ9aT/2u2lEijyzLFotF7RSgPmwJavn1OnnuOPpuvkHtIENGY0s4qaaZPXv2qlWrgh9//PHHkydPxpZ6RPGLLh5Y9TKXMYEKAJHkg3a+soXfNyMaV8gcYrgjwueff37r1q1NTU1vvPFGa2vrJZdcUlFRcdllly1fvvyXv/xlaWnpH/7wh7///e+jmjVyGTLy9SkZg5s+tk5bqHYWAIBhOeClKz6Vn5mnc0T7rM5wR4RWq9XhcPzsZz87/fTTHQ6HKIpE5HA4vvjiC4vFsm3btqeffnrZsmWjGTWyxS+8aOCjFygKlv8AQGy4bp18cT6bnxqdK0UPNdwR4eLFixcvXvzt2zMzM//85z+HNFJ0MhZMFKzxnqq15glzjn9vAABVrWhUdvTyFaed1DqSSBEVq1EiRNyCC/s/eA6DQgDQuDY3v2WD/Oz86Dx8/ttQhOFjLp9Biuxt2KJ2EACAo1I4XfqJfHOlrjIx+neKBqEIw4ixuAUXDnz0wvHvCQCgknurFSL6ZXkMtUMM/ahaYJkyT+7ulHbVqB0EAOAIPu/if6uWV5ymE2JlNEiEIgw3QWdbcMHAqpfUzgEA8E29PrrkY/lfc3RZtliqQRRh+Fmnnym11Pv37lI7CADA1zjRFZ/KF+Sy72bHXC/E3A+sOmYQ406/sP/dZ9QOAgDwtf+tVvYO8rtOiY11oodDEarAOuscqbVRaqlTOwgAABHRhv383ir5hQU6MSY7ISZ/aLUxgxi38KL+9/6tdhAAAOr10fdXyY/M0eXExdbU4EEoQnVYZ3wn0NXua6pWOwgAxDROdPlq+fwctjT2pgYPit2fXF1Mp49b9P3+t1eoHQQAYtodm5Veid89NRanBg9CEarGOnWh7O7zNWxVOwgAxKg3WpTH6pUXFugMsV0Fsf3Tq0sQ4hdd3PcOBoUAoII6J79mjfzaGbo0S4xODR6EIlSTZfI8Lnm9NRvVDgIAsaXXR4s/kP8yVTd1TKy3IKEIVcZY/JmX9L2zApekAICwUTj98JPAkmx2RSEqgAhFqDpz5Wwi8lStVTsIAMSK32yUfTItj+0FModCEaqNsYTvXtW38gke8KsdBQCi39ONyqu7+Qun6/V4+f8KfhPqMxZM1I/NdK15U+0gABDlVnfw32yU31qkSzKqHUVLUISakPDdqwc+ekFx96sdBACiVo2TL1sV+Pc8fXECFsgcBkWoCfqxmZaJc/s/eFbtIAAQnToG6ez35P+drluQhhb8JhShVsR/59LBTR8H9rerHQQAos2An855P/CzEuGH4/GafwT4pWiFYLPHzb+gb+UTagcBgKgic/rhJ/KUZHbLBLzgHxl+Lxpim3eev2OXr2GL2kEAIEpwoqs+k2WF/3M2DpY4KhShhjCdPv6cHznfeBzH1wNASNz8hVzv5M8vwMESx4LfjbZYJp7KDBjjbyMAACAASURBVOLgxo/UDgIAEe/WL+WP2vnbZ+ptBrWjaBuKUGMYSzj/p31vP6V43WpHAYAIdv925ZVd/P2z9A4cMng8KELNEbOKTGXTcalCADhh/6hRHqpRVp2jG2tWO0okQBFqkX3JlZ6qtVJLndpBACDyPN2oLK9SPjoL11caLhShFgkmq/3cK5wvP0yKonYWAIgk/9eg/O5L5YOzdDlxaMHhQhFqlGXq6cxkda19S+0gABAxHqtTbt+sfHy2rsiOFhwBFKF2OZb9T//7/5H7utUOAgAR4JFa5S/blP+erStAC44QilC79GPSbTPP7nvjUbWDAIDW3Vut/LVKWXW2Lj8eLThiKEJNi1v0A6mlwVu7Ue0gAKBdd21RnqhXPjtXl4t5wROCItQ0ZhATLrjW+co/ueRTOwsAaI7C6YbP5Zd2KZ+co0+3ogVPEIpQ60wlU8Wc4r63nlQ7CABoi0+mSz6Rq3r4p+fqcbzgyUARRoCEC67zVH/u21mldhAA0AqnRIveDfgVevc7eruodpoIhyKMAILJ6vj+L3qf+xv3edTOAgDq2zvI570VmJjEXlygM+GqEicNRRgZTEWTjQUTnG88pnYQAFDZ1m4+4w358kLhgZk6AdOCoYAijBj2pdd4677EClKAWPbSLuXM9wJ/myH8shyv3iGDX2XEEEyWxB/c2PvCA8qgS+0sABBunGj5NuWmL5R3ztRfkIuX7lDCbzOSGAsmmstn9L3+L7WDAEBYDfjp/A/lt1qVDd/VT0nG/tAQQxFGGPuSq3zNOzzb1qgdBADCpKGPT38jkGalVWfjMIlRgSKMMEw0JV7+m96XHgp0d6idBQBG3XNNypw3AzdWCA/P0hnwgj068HuNPGJmYfzC7/c8dTcP+NXOAgCjxSvTDZ/Lt29WPjhLf1URXqtHEX65Ecl26nd1juS+N59QOwgAjIo6J5/+RqDXR18u1U9MwqTg6EIRRibGHD+40bt9vadqndpRACDEHqtTTn0rcGOF8PQ8nc2gdpoYoFc7AJwgwWxLvPx3Bx79oyE9T580Tu04ABAC7W7+kzXyPg99eq6+OAEDwTDBiDCCiVmFcadf2LPiL1wOqJ0FAE7WS7uUKa8HKhLZuiVowbBCEUa2uHnn6+IT+17DkYUAEazTQ+d9KN+1RXnnTP09U3UiXpjDC7/vCMdY4qW3+JqqXWvfUjsKAIyYwumftcqEV/2TktmXS/WTcbC8GjQ6R/hy45trOzaonSJi8FJDoO4J/f63mVErR9vK/Kv/FFJo6P8KJ5kT56RwzolkTpxI4V99i/L1twe/OvQRIyIS2GHv2hij4OmGGZHAiBHpGBEjHWMCkcBIx0hgQx8M/ScQXmO0gitclkmRuaKQIpOicEUhLhPnxDlXFCJOyiEbhKJwzhljJByyFTBGjDFBR8RIYMQEJggk6EgQGNORIDCdjgRNX5rBHaA9Li4wWmRnbZ10XafagSKBWWe6f9GfWUj/mjVahGdknTotY7IgYMA6XNKehv63n3L84EZdQvLoPYvCqcdHvRLv9VKPxJ0SOX3klKhfoj4/75eoTyJXgPdLZNWT1cBserIZyKQnm8hMOjLpKE4kAyOzjvQCmfWkF8iiJyISiGz6Q7ZsRnEGIiKv12symYjIJ5MkH/LzcvLKnIgCCg0GSA7+n8gdIF+AvDK5/OSRuU8ml58GJHIFuCtAekZxBooXmf2r/8eJlCiSw0QJIiWIzGGkZBMza/rFM0Jwrrj75f5exdUrD/TKfT2Kq1d2D/DBAdndT8R1FjszWQSThZnMzGgRjBbBZCa9nulFJpqYIDCT5eCDMdHk9flMJhP3eYmG3jpxyUeKrHgHuSKT5OOST/ENco9H8Q4qXg/3uZTBfi5JgjVOsMQLljghLkEX59DFO4S4RF18ghDnYOrVZJ9ED9Uon/fy/yljZ2XiGhIjEPAGQtuCpNkiTDDaU83jUIQjkDje5VbcLz455hf3CSbrCT+MzKlzkLe5qdPDW93UMcjb3dTl5e1u6vLwbh8lmyjZxMaYaKyZJZso2cIKHOQwUqKRJRop0UiJRpZgDNl2OjAwEBcXF6IHo8EAOSXe46MeH/X4hj7o8vCafjrg5Qe8tN9LnYOciNKsbKyZxplZmoXSLCzNSukWlmqhLBuzavSPRk2Ky+nvaAl0tQW6OwL79wYO7A0c2CuYrTrHWF3CGJ1jjH5Msa5wjC7OIcQ5dPEOJppG+hQntiVwOaAMOOWBHmXAKffuDzj3yy3tcvdm2blfHujVxSfpx6Tpk1N1yWmGlAz92Ex94jhio9tKkkKP1il3bZEvyhO2XKDDNXVHamBgIOSPib/p6GGbfW6go6VnxT3JV99Ox3sP4fJTi4vvGqAWF9/j4q1u2uPie1y0z8OTTSzDSqmWof/PT6MUk5BupRQzSzFRRL93tejJomdpQyONo/4k7gC1u3mXhzo9fO8gtbv59l5qdysdHtrj4kYdZVhZto0yrSzTxrJtlG1juXGUahnlV1DNUDwuf/su/95mf2dLoHOPf98eIjKMy9anZOiTUy3ZxfrkNP2YtBNou5BjOr0uIfmIu0m4HJB79gUO7A02t69+c2Bfq+xy6lMyDWOzDKnZhrRcQ1peCHexcKIXmpTfb1IK4umDs/SViTGyvUQAFGFUSTj/p/sf+b3zjUcTzvtp8JaAQnvcvLmfmgd48wBv7qddA3y3iw8GKMfGcuIo28aybKwykbJtQqaN0iwM5zO06qnQzgrtdMSy7PFRq5sH3ze0uvmbe6hlQNnt4j0+yrKxXBvlxbPcOJYXR3lxLD+eRcFbfsXVJ+1pkPbU+/c2+9ubZVefIS1XTMszpOdZJs8zjMsWbHa1M44Y0+n1Y9L1Y9Kp5Osbuc/j72oNdO7xd7a4Pn3D397MFdmQni+m5xkyC8SsIn1y6ok93Uft/DcbZR2jx+bq5qeiArUFRRg9Agq1uISmhb/LePbmd3qf+3f6hTv7qdXFx1mGXpRz49j5OZQXL+TYWIpWVtVEnuDu3wnfejvvlYcG2c39vHmAr++i5n6leYAbdTQ+no2PZwV2Nj6eCuJZoV3r7cj9ktTaKO2ulVob/C31isctZhUaMgssk+cbFl+pT04b7f2HamFGs5hZKGYWHrxF7u/xtzf725s829b0vfkkl7xiVqGYVShmFYm5pYLl+HtrP+7gd22R29x01ynCBbkRvUslaqEII9V+L9U5eZ2TN/Tx+j5q6OMtLj7OwgrizZPn3vnjT36dlxKfsPDs3DhmxNKPsDDpqMjOir41jtznocY+vrOf7+znK1uosV9p6OOW4KAznhXaWVEClSSwvDiVx+KKy+lrrpF27fDtqvHv3WUYlyXmlJjLZ9jPvjyKm++4dPGJuvhEU8kpwU/lgV7/nnppT4Pr0zekZ5YL9mRjbomYW2bMK9OPST/0GznR23v4X7bKTol+M0H4Qb6AfS2ahSKMADKn3QO8ro9qnbzOyWt6eX0f50RFdlaSwIrsbNZYKrQL4+MPdt6YwIS/7H/wZnu6zTjpNHXDw1gzjTWzOeMOK5K9g7yhjxr6eEMf/6yO1/VRu5tn2ViZgxXZqSSBlSSwogQWP8rnmZT7e31NVdLOal9TldzfI+aUirkl9nOvELMKmWgc3eeOTLo4h65shqlsBhGRovg7dvl21fgatvS/92+SA8bxlcb8CiGv4o3BjHu2KQKj300Uzs8RMAzUOBSh5kgKNfbxWievddKOXl7n5A39fJyZFdmpzMGmj2GXFwjFCWzMMRci6JNSk6+568A/fiuYbabiKeHKDsOVZmFpFpp3yFxR8N+9zsnr++iDdv73HUp9H08QWUkClSSwUgcrtrMyB0s+6QUoisfl21nlq9/ibdyqDDiN+eXG8ZXWmWcZ0nKPu8YKDiMIhvR8Q3o+zVlMRIHuzv211VVbtllWvljJpf/kTciZNMlknySwFLWDwnGgCFUmKVTn5LVOvqOX1zhpRy9vcfFsGytNYCUJtCSb3TJBKLYz88j/oQypOUlX/vHA47cnX/lHMbd0FLJDKIkClTlYmeOwsUOLi9c5qcbJNx3gzzQqtU6uY1TmYCUJrNzBShysLGF4072K7Ntd66vd5G3Y4u9sMeaWGgsnJV36G0N6Xszu8wytdfv4QzVj3mubd9GkBdddIhTx/d7GLb76LX1v/p9gtpoKJxmLJ5sKJ2nnlBdwKMY5P/69Ttorr7zy3HPPvfzyy8O8v9vtNpvN0Xcc4cHa297La520vYfvcfNcGytzsFIHlSawUgcrtLMQnmnQW7ep9z/3Jl19m5hVFLIHDaPQHkcYBTo9tKP3q3dOvXxHL2eMyhysNCG4FR1WjbJzv7f2S2/dJl/jVn1SqrF4iqlosphTwvSRd2kfbW4JbW7+75386UZF5vSzEuHHhcI3l0Fx7u/Y7W3Y4qvb5NtVI2YWmIqnmEpOMaThLcgJGo0tAUU4inwy1fcdtfaCL16F9lFfIuGt2djz7P8m/fhWY37F6D7TKNDmy5+m7PPQjl5e81U11vXIlYN15/u+nNGzIV5y+nKnJJafklI5WbAlqJ30pGhqS3D56bUW5elGZcsBfmGecOl4YdbY47cal3y+pipv7Zfe2i+5z2MqnWYqnWYqwjBxZFCEmjYYGBrt1Xw1vdfq5nlxrDQhrLV3RL7Grd0r7kn84c0RN1+oqZc/LVO8bm/NRu+OL7x1m7h9THf2tOqxU9fqC2v6aHsPJxraoVrqYCUJrCSBMqwRNhzRwpZwwEsr9yiv7VY+7eCnpQqXFbDFWcKJrcoOHOjw7vjCW7NBaqkTc0pMpdPM5TN1iZhNPD4UoYb0+KjWyWudvP6r5uv08CI7K04Ymt4rc7Dx8Ro6OF3aVdP95J0JF91gLp+hdpYR0MLLn5bJvV2e7eu929dLLXVifqW5bJqpbLrOnvSNu3V5aIeT1/YGt1Ve08s9MgW31eIEVmynkgSWG8f0mtlcv03FLWF7L/+wna9sUbZ080Xpwnk57OzMb+0CPVHc5/HWb/bu2ODZ8YXOnmQun2GumGlIz8eO06MZjS0Bi2WOT1KouZ/X9Q2td6/v4/VOHuBUZGelCawogf00lQVfR3Qa3nTF3NKkn9zR/dgfud9nwTEVEc7fsdtTtc5TvVZ2HjCXTbfOOTfpyj8d44CHFDOlmNmhJzTp/eqdXJ2Tf9rB6/po7yDPtbGiBFZoDx4QyQrtIVikGqE6BumjvcpH7fzDdsWsYwvT2Y0VwsJ0wRTqo3KZ0WyunG2unO3gXNpd49m+vvvpe7jkM1fMNFfOMuZXaPwCGtEBI8LD+GTaNcCbB2hnP2/o4zv7eWMf7R3kGVZWZKfiBFZoZ4V2VpzAxkXmXn1/x+4Dj9wat/D7tjmL1c4yLBgRfo1zqaXeU73Ws20tKbKpcra5cpYxpzRUxzx45aH3eQ19VO/k9X28sZ8TUUE8Gx/PCu2swD500rhjH7ozSkZ7S5A5be/lazv551388y7e6+Pz04SF6eyMNJYfH+53uIF9rZ7qdZ6qtYHuTnPZdFPlbFPRZGbQ9umIwgW7RkMmoFD7IG9x0e6BoRNPB8/D2eXlWTaWH0f58awgnhXYWUE85ah9yo/QCnR3dj/2R2PBxITzrtH+m00UISmKr3m7p2qtZ9sawWwzV84yV842ZIwPz5Mf8FJjP2/s4439fGc/NfXz5n4uKZQfz/Lihs5VmxtHOTaWHTe6h/+HfEtwB2h7D9/Ww7f18KoeXtXNM6xsRgqbPY7NTGHFCZrYNSk793uq1nmq1/lbdxpLplgq55jKpmnhbOYqQhGOTL+f9rp5l5f2unmnh1pcvN1N7YN8j4v2e3mKiWXHUa6NZcdRjm3oLMmZNk3v3gwVxevueeovxFji5b89mWs2hUHsFqEiexu2eqrWeqrW6RKSLRPmmCtn68dmqh2LiMgpDZ1PdbeLdg/wg5cx0TPKsLJMG6VbWPCDsWaWaqZxFkoxnewE5MlsCcHr3zYP0FCj9/HGftrn4SUJbEIiq0xklUlsUhJL0PCIS3H1BceI0q4aY8FE84Q5pvLpGv/jHSWxXoR9EsmcnBIPKDTgpz6J+iTeP/QBHfDybh91e/l+L+330n4vNzBKs7IU09C15bKsLN1KGVaWZaNx5qga5J0IRXa++ohvZ1XS1bfrk8apneaoYq0IuRzwNWz1bPvMU/25PjnNPGGOecIcLf8DHarXN7Sjpd3N29281U1dHr53kPZ5aL+XJxopyciSTJRsYskmGmMiu8gSREoQyS6yeJGswcs468isY1YDfeNo2m9vCZJCbj8N+LlPpn4/ufzU7eM9PjrgpW4vP+CjjkHe5qY2N/crlGVjOTYK7uMdH88K7JRj0/TioKNRBl3eHes929b4dlaJ+RWWiXNN5TMEs03tXOETQ0V40zrvk006Igp2XpBdJIGRQ2Q6geINFG8Y+vuxi2QXKcnIkk1Df2kpJhprPpGzscQa12crBz58PvFHvzPmlaud5chipAiH+m/rp57t6/Vj0i0T55onzNE5omcxPSfa56FuLz/gpW4f7/LQAS/1+3mfRL2+oXe07gC5/eSRuVcml5/8ChGRQSCbgYiIc84YI6LBAPnkr79k0zOjjuwiWfWUZGKJRkoyDnVtqoVlWindqumh3glTvIPeHes9W9f4GreKeWWWiaeaKmbGQiPG0KrRWyvk304SBUHQCxQXeSfBiBi2uUv0Y9J7nvqzde6S+DO+jxXbYfZV/33m2f65PiXTMnFu/FmXhfBKsNrBiMaZaZyZffXZcPkVcvmJiFwul81mIyKLnnBBFSISTBbLlAWWKQu4z+PZ8YVn62fOVx8R88osE+fGSCOGkEaLUBTIbMQZgMPBVDwl5eZ/9P7n3v0Nv0n84a+/fQgahJ6i+HbXerZ+Orh5tc4Wb554asqND+iTTvCKr9HNIJDDSESkl3gcrodxJMxotkyeZ5k8j/slX8Pmwa2fOV99RJ+aY5k41zJlfiReMzn8NFqEEE66OEfyT+7s/+DZrv/9H8fFv4q4s89Eim+P/8be9FBUjv9AFcwgmspmmMpmHBwj9r/7DMaIw4EiBCIiEoT47/zQWDCh55m/WiafFn/WZThoKVS4HPDVb/Fs+8yzfb0+JcMy8dT4sy5F/8Ho+XqMONSInzpf/aeYV2aeMNdcMVOwRP+k+0ihCOFrxvyKsTc/7Hzl4X3Lf+pY9nNj4US1E0UwHvD76jcNbl3j3fGFYVyWeULUzv+BZn2zEbet6XvtETG3dKgRrfFqB9QKFCEcRrDGJ172W2/Nhp7n/2YaP8H+3avx1zIiXPJ5azd6tq3x1n5pSM81V86xn/tjzLyCur5uRMnr3bFhcNtnfa8/asgqME+YY66YrYt3qB1QZShCOAJT6bRxt/yr750V+5b/1P7dqy2T52FB6bEpHpe3ZoOnap2vfrOYXWyeMMd+3jW6uFh/fQGtYaLJPOlU86RTuV/y1n7p2bam/+2nDONyzJWzTJWz9Ylj1Q6oDhQhHBkzmhPO+6llyoLeF//u+uwN++IrI/FyhqNN7u/xVn/uqV4n7a41jq80Vc52LPs5xtCgfcwgmitnmStn8YDf17DVU7W2/6MXdQlJ5orZ5spZhtQctQOGFYoQjkXMKhz7qwcHN3/c++z/6sdm2RdfEWt/IUfk79jt3b7es319YH+7qWSqdeZZSVf8IcbPAAkRiukNptKpptKpDkXx7drhqf68+/HbiDFT+Uxz2XRjfrn2z0h88lCEcDyMWaYsME881b3mrQP/+K2x5JT4RRfrk2PuoDce8Puaqr01G7zb1xMxU/kM+7k/EvPKmQ5/RBAVBMGYX2HMr6ClP/Hv3eXZsb7vzScD3R2m4immsummoslRvKsDf8MwLEynt5221DJ9kevjV7ru/4UxvyJu3vlibqnauUad3Nvlrf3SW7PBt7NKn5prLpuWdNVtGBZDdDOk5RrScuMX/kDu7/XuWO/Zstr54t/1qTmm0qnmkmmG9LwoWzSAIoQREEyW+LMujTv9QveGD3v+c69gi4+b/z1zxewoOwkQl7y+nVXe+i2++k2yq89Ucop58jzHxb/CAVgQa3TxDuvMs6wzz/pqj8jG7hV/4b5BY9FkU+FkY9EkXXyi2hlDQKMn3VbrwrwwApx7qj93ffJKoGef5ZTTLaecbhiXFfInCdtJt7kckFrqfTurfA2bpdadYlahqWiysWiSmFEQZW9+I1SMnH49IgS6O3z1W7z1m32N23T2JGPRZFNBpZhXHp6T12j3pNt+v99gwLmxYwxjwVVn/s6WwY3/PfDI73RxiZapp1smnybYEtQONyzcL0l76n07q3xN1VJLvSEl0zi+Iu70Zcb8SibivJYAR6ZPStXPSrXOOpsURWpr9NVvcX26Unrmr7rkNGN+hbFggjG3NLImFE92RHjffffdeeedgUDgtNNO+/e//223H/kErxgRRj/OfY1b3Rv/692+Xj8201Q6zVRyipgx/iSHUyF/9xc40CG11Eq766Tddf59LYa03OACATGvXDBZQvhEEFoYEWoclwP+PQ2+pmpfU7W0q1aISxBzisXsEmNOiSEtJ4RLTzV3PcLNmzefccYZ69evz83NvfDCC3Nycu6///4j3hNFGDu4HJCatntrN3pqNvLBAWPJKca8cjG7yDA26wSmEk92o1dkf1ebv63J394ktTX523cy0STmlIg5JcbsYkPGeJxSNVKgCCMJ5/59e6TdddLuGml3XaCn0zAu25AxXkzPN6TnG9JyT2aPi+aK8IYbbvB4PI8++igRrV27dvHixd3d3exIIwAUYWwK9Ozz1X7p210r7amXnQfEzAIxu9iQlqsfk64fkzacGYURbfRyf6/s7Ap0tQf2tfq72gJdrYEDe3UJYwwZ+WJ6viFjvCE9D2d7iVAowsjFfR7/3l1Se1PwLam/s0UXn6hPydCPzTKkZOhTMvRJ43T2pGGOGjU3R7hz586FCxcGPy4tLe3t7T1w4MCYMWOOeGdJknp7ew9+mpCQcMTKhGiiTxyrn32OdfY5RKR4XFJLvdRS792+3r+/PbC/nRlE/ZgMffI4wWrX2exCnENnswtWO+l0gslCgsB0Bi4FFIErXjcRccnHA34ueRX3gDLYr7j7FXe/7OqTe/fLzv2ycz8zWvSOFP2YNP3YLMvEufqUDH1KBsZ8AOpiRrOYW/r10VaKEujZF+hq9XfukVobBzd9HOjuUAacQlyCzjFW7xgjxDkEa7xgiROscTprPDPbmCAwk4WImMFE/gCRlorQ6XQGrxlNRMGK7u3tPWIRNjc3v/fee3l5eQdvWbFixYIFC472yIODg7IsY0QYbTKKhIwikShYTcpAr3KgQ3F2Bdz9fmc3b9+luPu5u58RV7yDpCikBBSfZ0DQMWPwb0BkBpH0IrPEMbONWWyC1c4yxxnKZhrtycyefGjnyUQykc8nkU9S6aeFUHK73XjrHD1McZRVyrJKDURDyywVWenvUfq6Fed+2eUMuF38QKcy2M8HXeQb5IrCvYNERAEf14vsxoeHv/jAYrEct0pOqgiTk5P7+vqCHzudTiJKSUk54j3z8vKWLFky/F2jjDHsGo1+NhulZh77LtghBkGc84NvuyE6xdspI/e49xoYGLCF+jXhpJqmpKRk69atwY+3bt2ampqakBAZ6+YBAACCTmpEeMUVV5xyyikffvhhaWnp7bff/pOf/CRUsQAAAMLjpIqwsLDwqaeeuuWWW3p6epYuXfq73/0uVLEAAADC42Qn4c4///zNmzfv3r37/vvvF8WQLc976aWXmpqaQvVoELn+7//+r6urS+0UoL6HH354cHBQ7RSgvnvvvVdRlNA+pkZXo7z++uvbtm1TOwWo77nnnmtsbFQ7BajvX//6V2dnp9opQH3/7//9P6/XG9rH1GgRAgAAhAeKEAAAYhqKEAAAYlqYrkf4wAMP/P73vz/a4fbf1tXVZbPZLBZcDSDWdXR0JCYmGo24KFKsa21tTU1N1etxLfFY19LSkpWVNfzTDF188cV33nnnse8TpiJUFKWxsXH41yyUJMlgMOCMSuDz+dCCQNgS4Csj3RJSU1PNZvOx7xOmIgQAANAmzBECAEBMQxECAEBMQxECAEBMQxECAEBM0+Ja5M8+++z1119PTEy84oorUlNT1Y4D6ti/f/+mTZv27Nlz6qmnFhcXqx0HVLNly5YPPvigq6uruLj4hz/84XFXAEJUUhTl5Zdfrq6udrvd5eXlF198sclkCtWDa25EuHLlyqVLl2ZmZra2tk6fPv3ghX8h1ixatOi222679dZb16xZo3YWUM3AwMA555yzb9++rKysZ599dtasWT6fT+1QoAKv1/v8889brdacnJzHH3/8jDPOCOEhD5o7fGLmzJlXXHHF1VdfTUTz58//3ve+d/3116sdClSgKIogCHPnzr388suvuuoqteOAOhRFCQQCwSvbeL3etLS0V199dd68eWrnAjU5nU6Hw7Fr166cnJyQPKC2RoQ+n++LL74444wzgp8uXLhw9erV6kYCtQiCtjZOUIUgCAev78Y59/l8NptN3UigujVr1owdO3bs2LGhekBtzRF2dnZyzg+eiW3s2LEdHR3qRgIAjbjllltmzpw5ZcoUtYOAas4999yNGzdKkrRy5coQzhZrqwiD52ALBALBT/1+fwgv9gsAkeuBBx549913P/30U5x5MZY9++yz/f39zz///LJly6qrq5OTk0PysNra+5SSkqLX69vb24Oftre3Y9UoAPzjH//4+9//vmrVKrwgxLj4+PiMjIybbrrJ4XB8/PHHoXpYbRWhXq8/66yzXn75ZSLy+/2vv/76kiVL1A4FAGp68sknly9f/tFHH2VmZqqdBVTj8XgOLu3s7Oxsa2vLysoK1YNrbtXo5s2bzzzzzEWLFjU3N4ui+OGHH2LvaGz69a9/vWrVKOSqoQAAAOlJREFUqvr6+qSkpOTk5Pvuu2/u3Llqh4Jw27dvX1paWkZGxpgxY4K3/OlPf1q8eLG6qSD8Vq5c+atf/WrKlCmKoqxateqiiy56+OGHQ/XgmitCIurq6vrkk08cDsf8+fNx+bGY1dzc3Nvbe/DT8ePH2+12FfOAKiRJqq6uPvSWnJycpKQktfKAinbs2FFbW6vT6SoqKsaPHx/CR9ZiEQIAAISNtuYIAQAAwgxFCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMQ1FCAAAMe3/AzRtCCP1XOH2AAAAAElFTkSuQmCC", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "xs = range(0, stop = 3, length = 100)\n", + "using Plots\n", + "plot(xs, f1.(xs), label = \"f1\")\n", + "plot!(xs, f2.(xs), label = \"f2\")\n", + "plot!(xs, 4 * ones(length(xs)), label = nothing)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Clarabel.MOIwrapper.Optimizer" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "import Clarabel\n", + "solver = Clarabel.Optimizer" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "solve (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "function solve(d)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = K, maxdegree = d)\n", + " optimize!(model)\n", + " println(solution_summary(model))\n", + " return model\n", + "end" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "The first level of the hierarchy gives a lower bound of `-7``" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 31\n", + " constraints = 40\n", + " nnz(P) = 0\n", + " nnz(A) = 73\n", + " cones (total) = 6\n", + " : Zero = 1, numel = 10\n", + " : PSDTriangle = 5, numel = (6,6,6,6,6)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 1.2590e-01 1.2590e-01 8.33e-17 6.99e-01 6.62e-01 1.00e+00 1.51e+00 ------ \n", + " 1 4.8332e-01 5.0333e-01 2.00e-02 1.40e-01 9.41e-02 1.86e-01 3.32e-01 8.02e-01 \n", + " 2 1.3995e+00 1.5138e+00 8.17e-02 8.66e-02 2.59e-02 2.10e-01 1.08e-01 7.85e-01 \n", + " 3 2.7854e+00 2.9400e+00 5.55e-02 2.03e-02 3.36e-03 1.83e-01 1.58e-02 8.78e-01 \n", + " 4 4.0242e+00 4.2592e+00 5.84e-02 1.43e-02 1.34e-03 2.61e-01 7.20e-03 7.46e-01 \n", + " 5 5.4090e+00 5.5096e+00 1.86e-02 4.16e-03 3.04e-04 1.09e-01 1.81e-03 8.27e-01 \n", + " 6 6.2811e+00 6.3385e+00 9.13e-03 1.73e-03 1.07e-04 6.15e-02 6.79e-04 7.22e-01 \n", + " 7 6.9685e+00 6.9720e+00 5.12e-04 6.60e-05 3.84e-06 3.75e-03 2.52e-05 9.69e-01 \n", + " 8 6.9993e+00 6.9994e+00 1.29e-05 1.66e-06 9.63e-08 9.46e-05 6.33e-07 9.75e-01 \n", + " 9 7.0000e+00 7.0000e+00 3.48e-07 4.54e-08 2.62e-09 2.56e-06 1.72e-08 9.73e-01 \n", + " 10 7.0000e+00 7.0000e+00 1.18e-08 1.56e-09 8.90e-11 8.65e-08 5.85e-10 9.66e-01 \n", + " 11 7.0000e+00 7.0000e+00 2.34e-10 3.13e-11 1.84e-12 1.72e-09 1.17e-11 9.80e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 3.80ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -7.00000e+00\n", + " Dual objective value : -7.00000e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 3.79969e-03\n", + " Barrier iterations : 11\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model4 = solve(4)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "The second level improves the lower bound" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 108\n", + " constraints = 128\n", + " nnz(P) = 0\n", + " nnz(A) = 266\n", + " cones (total) = 7\n", + " : Zero = 1, numel = 21\n", + " : Nonnegative = 1, numel = 2\n", + " : PSDTriangle = 5, numel = (21,21,21,21,21)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 2.8313e-01 2.8313e-01 0.00e+00 7.53e-01 6.03e-01 1.00e+00 1.82e+00 ------ \n", + " 1 5.4905e-01 5.6026e-01 1.12e-02 1.28e-01 7.06e-02 1.86e-01 4.16e-01 8.05e-01 \n", + " 2 1.0075e+00 1.0482e+00 4.04e-02 3.51e-02 1.22e-02 8.87e-02 1.08e-01 8.48e-01 \n", + " 3 1.7352e+00 1.7929e+00 3.33e-02 8.17e-03 1.68e-03 7.10e-02 1.55e-02 9.20e-01 \n", + " 4 2.2703e+00 2.3425e+00 3.18e-02 3.66e-03 5.84e-04 7.97e-02 4.20e-03 8.20e-01 \n", + " 5 2.5204e+00 2.5826e+00 2.47e-02 2.51e-03 3.63e-04 6.81e-02 2.42e-03 6.21e-01 \n", + " 6 3.3688e+00 3.4392e+00 2.09e-02 6.50e-04 6.62e-05 7.25e-02 3.73e-04 8.78e-01 \n", + " 7 4.1613e+00 4.2336e+00 1.74e-02 3.75e-04 2.25e-05 7.36e-02 1.14e-04 8.80e-01 \n", + " 8 4.9013e+00 4.9482e+00 9.56e-03 1.66e-04 8.18e-06 4.76e-02 4.21e-05 8.78e-01 \n", + " 9 5.7265e+00 5.7548e+00 4.95e-03 6.35e-05 2.06e-06 2.86e-02 1.12e-05 8.50e-01 \n", + " 10 5.7843e+00 5.8135e+00 5.04e-03 6.09e-05 1.89e-06 2.95e-02 1.03e-05 2.28e-01 \n", + " 11 6.4423e+00 6.4536e+00 1.75e-03 1.28e-05 3.67e-07 1.13e-02 2.07e-06 8.34e-01 \n", + " 12 6.6492e+00 6.6500e+00 1.19e-04 7.56e-07 2.24e-08 7.94e-04 1.26e-07 9.69e-01 \n", + " 13 6.6662e+00 6.6663e+00 3.10e-06 1.97e-08 5.83e-10 2.08e-05 3.28e-09 9.74e-01 \n", + " 14 6.6667e+00 6.6667e+00 8.84e-08 5.65e-10 1.66e-11 5.93e-07 9.36e-11 9.72e-01 \n", + " 15 6.6667e+00 6.6667e+00 2.63e-09 1.69e-11 4.96e-13 1.76e-08 2.79e-12 9.70e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 11.7ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -6.66667e+00\n", + " Dual objective value : -6.66667e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 1.17054e-02\n", + " Barrier iterations : 15\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model5 = solve(5)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "The third level finds the optimal objective value as lower bound..." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 288\n", + " constraints = 323\n", + " nnz(P) = 0\n", + " nnz(A) = 739\n", + " cones (total) = 8\n", + " : Zero = 1, numel = 36\n", + " : PSDTriangle = 7, numel = (55,55,55,55,...,55)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 3.3234e-01 3.3234e-01 2.22e-16 7.75e-01 7.03e-01 1.00e+00 1.51e+00 ------ \n", + " 1 4.7370e-01 4.8104e-01 7.34e-03 1.20e-01 7.54e-02 1.77e-01 3.55e-01 8.03e-01 \n", + " 2 7.3313e-01 7.6805e-01 3.49e-02 4.16e-02 1.96e-02 1.12e-01 1.54e-01 7.48e-01 \n", + " 3 1.1439e+00 1.1684e+00 2.14e-02 7.53e-03 2.35e-03 4.09e-02 2.71e-02 8.65e-01 \n", + " 4 1.5684e+00 1.6151e+00 2.98e-02 3.00e-03 6.64e-04 5.81e-02 7.91e-03 8.51e-01 \n", + " 5 1.8613e+00 1.8904e+00 1.57e-02 1.41e-03 2.53e-04 3.50e-02 3.10e-03 6.74e-01 \n", + " 6 2.1699e+00 2.1913e+00 9.85e-03 5.14e-04 7.66e-05 2.40e-02 8.88e-04 8.03e-01 \n", + " 7 2.5021e+00 2.5220e+00 7.93e-03 1.85e-04 2.34e-05 2.11e-02 2.37e-04 8.01e-01 \n", + " 8 2.7896e+00 2.8141e+00 8.76e-03 1.17e-04 1.10e-05 2.54e-02 9.20e-05 8.08e-01 \n", + " 9 3.2619e+00 3.2812e+00 5.91e-03 3.96e-05 2.84e-06 1.96e-02 2.16e-05 7.88e-01 \n", + " 10 3.6591e+00 3.6805e+00 5.86e-03 2.80e-05 1.09e-06 2.17e-02 7.16e-06 9.60e-01 \n", + " 11 4.0143e+00 4.0278e+00 3.36e-03 1.31e-05 4.96e-07 1.36e-02 3.07e-06 7.92e-01 \n", + " 12 4.3776e+00 4.3897e+00 2.76e-03 7.68e-06 2.25e-07 1.22e-02 1.31e-06 6.54e-01 \n", + " 13 4.8717e+00 4.8798e+00 1.67e-03 2.67e-06 6.42e-08 8.16e-03 3.48e-07 8.11e-01 \n", + " 14 5.0064e+00 5.0151e+00 1.74e-03 2.22e-06 4.55e-08 8.76e-03 2.29e-07 5.98e-01 \n", + " 15 5.3203e+00 5.3231e+00 5.17e-04 6.99e-07 1.36e-08 2.76e-03 6.96e-08 9.90e-01 \n", + " 16 5.4810e+00 5.4813e+00 6.57e-05 1.07e-07 2.07e-09 3.62e-04 9.89e-09 8.52e-01 \n", + " 17 5.5042e+00 5.5043e+00 1.24e-05 1.45e-08 2.83e-10 6.85e-05 1.36e-09 9.58e-01 \n", + " 18 5.5078e+00 5.5078e+00 6.98e-07 8.14e-10 1.59e-11 3.86e-06 7.64e-11 9.44e-01 \n", + " 19 5.5080e+00 5.5080e+00 5.33e-08 5.62e-11 1.10e-12 2.94e-07 5.30e-12 9.84e-01 \n", + " 20 5.5080e+00 5.5080e+00 1.09e-09 1.63e-12 2.93e-14 6.04e-09 1.09e-13 9.79e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 34.3ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -5.50801e+00\n", + " Dual objective value : -5.50801e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 3.43337e-02\n", + " Barrier iterations : 20\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model7 = solve(7)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "...and proves it by exhibiting the minimizer." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Atomic measure on the variables x[1], x[2] with 1 atoms:\n at [2.329520151218628, 3.178493153833861] with weight 0.9999999590079649" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "ν7 = moment_matrix(model7[:c])\n", + "η = atomic_measure(ν7, 1e-3) # Returns nothing as the dual is not atomic" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "We can indeed verify that the objective value at `x_opt` is equal to the lower bound." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "-5.508013305052489" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "x_opt = η.atoms[1].center\n", + "p(x_opt)" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "We can see visualize the solution as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=4}", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nO3deXgb1b0+8O+MpNFqy7IdO973fcm+J5AEEsqSNFAIW4GWpbTALYVCaUsXtltIL7dAgTasl0B/rGELW1kaCCQhC0kcO/Ea23Fsx44T27ItWdJIM+f3h0wIkMVOJM1Iej8PD48sy9JrZ6zXZ86ZGY4xRgAAANGKVzoAAACAklCEAAAQ1VCEAAAQ1VCEAAAQ1VCEAAAQ1VCEAAAQ1VCEAAAQ1VCEAAAQ1VCEAAAQ1VCEAAAQ1UJUhHV1dU899dToH+/z+YIXBsKI1+tVOgKoArYE8AvGlhCiIqytrf3www9H/3iPxyPLcvDyQLhwu91KRwBVwJYAfsHYErBrFAAAohqKEAAAohqKEAAAohqKEAAAohqKEAAAohqKEAAAohqKEAAAohqKEAAAoppKi9DXXC0N9CqdAgAAIp9Ki1Dctcm9c73SKQAAIPJplQ5wdJq0PLG9QekUAABhb8uWLQ8++KDSKU4Vx3F//etfs7KygvHkKi1CbWqu68v3lE4BABD2du7c2dfXd/311ysd5JTcfffdLS0t0VWEfHKGr+8AE92cYFA6CwBAeMvNzb3ooouUTnFK/vnPfwbvyVU6R8hptLrkTG9ni9JBAAAgwqm0CIlIm54nduxROgUAAEQ49RahkJ7vRRECAECQqbcItel5YnuT0ikAACDCqbcIdam5vkNdzCsqHQQAACKZeouQ02i1SWnerlalgwAAQCRTbxESkZCej72jAAARqb6+ft68eTk5Oa+++ur+/ftfeumlP/zhD6tWrQp9ElUXoS69wNuO9TIAABFoxYoVZ511Vmtr6/Lly1944YXnn39+3bp1r7/+euiTqLoIhYx8sQMjQgCASPPee+9t3bp17969Tz75pNPpvOOOOz744IOlS5cqEkbVRahLzfX1dDCfV+kgAAAQsVR6ijU/TidoE1K8XXuFjAKlswAARIh9DnbtFxIL4Stelsf/tPBb465zzz33scceW7hw4WWXXRbCIEen6iIkIiGjwNvehCIEAAiUFBN3xwQNC2ETFseF7rVOgtqLUJeeL3bsMSsdAwAgYuh4OiOVUzqFiqh6jpBGRoRYOAoAAMGi9iLUpeV5D7Qxyad0EAAACJY333wzLy/vgQce+M9//pOXl/e73/0ulK+u9l2jnKDXxif7utt0aXlKZwEAgIB57bXXBEHw3z733HPnz59/+FN6vT6USdRehESkyygQ2/egCAEAIonFYjl8WxCEw6UYemrfNUoj12PCYfUAABAUYVCEuowCXKEXAACCJAx2jQpped79e5nk4zRhkBYAAEajpqbmJz/5id1uv//++00m0zvvvLNv376MjIybbrqpsrIylEnCYETI6Y2auERfT4fSQQAAIGAefPDBiy++uLm5efny5Y8++mhFRcUtt9wyfvz4OXPmNDc3hzJJeIyxhIwCsb1Jl5KtdBAAAAiAl19+edOmTaIorlix4oYbbvjwww/99y9evPiTTz756KOPfvGLX4QsTBiMCIlIl57vxTQhAECkiImJ0el0ZrPZZrPx/DdNJIqifwdpKMOEyYgws3Bg53qlUwAARAJf34G+5/5CTA7ZK5pnn2OedfaR9xzrpNt33HFHbm7uOeecE7JsFDZFmFHo7cJ6GQCAANDGjbMt/y8WwrNua21Jo3nYihUr/v3vf69bt+7IMWIIhEevjJxfpmuvLj1f6SwAAGGO51X4Xvrwww8//fTT69atS0oaVWsGUHjMERKRkFkk7mtUOgUAAATeU0899fDDD3/88cepqamhf/UwKsJCcV+D0ikAACDwfvnLX/b09EyePDk+Pj4+Pv6+++4L5auHx65RIhKyihzr31E6BQAABMaRJ93u6uo6cs7SYDCEMknYFKE2JdvXd4B5XJzeqHQWAAA4VUeedDsuTslr2IfNrlFOo9WlZIudIT3dAAAARLywKULyTxO2YZoQAAACKbyKsMiLhaMAABBQYVWEWTiCAgAAAiycilCbmCq7hmSHXekgAAAQOcKpCInjdOkFYjuuVg8AAAETNodP+AlZRWJbg6FkmtJBAADCg1arffPNN7dv3650kFPS2Nio1QarsMKtCDMLnV/+W+kUAABh4/LLLw/xBd+DQRCE8vLyID15uBVhVnH/K48onQIAIGwIgjBlyhSlU6haWM0REmli4zmNVurrUToIAABEiDArQhq5DAUOqwcAgMAIxyLEZSgAACBgwq8IdZmFOKweAAACJfyKUMgq8nbsIVlWOggAAESC8CtC3mDmY2zennalgwAAQCQIvyKkkfUy2DsKAAABEKZFWOjFehkAAAiE8CzCrCKxDSNCAAAI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", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "scatter!([x_opt[1]], [x_opt[2]], markershape = :star, label = nothing)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/min_univariate.jl b/previews/PR347/generated/Polynomial Optimization/min_univariate.jl new file mode 100644 index 000000000..2e3f6a562 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/min_univariate.jl @@ -0,0 +1,45 @@ +using DynamicPolynomials +@polyvar x[1:2] +p = -sum(x) +using SumOfSquares +f1 = 2x[1]^4 - 8x[1]^3 + 8x[1]^2 + 2 +f2 = 4x[1]^4 - 32x[1]^3 + 88x[1]^2 - 96x[1] + 36 +K = @set x[1] >= 0 && x[1] <= 3 && x[2] >= 0 && x[2] <= 4 && x[2] <= f1 && x[2] <= f2 + +xs = range(0, stop = 3, length = 100) +using Plots +plot(xs, f1.(xs), label = "f1") +plot!(xs, f2.(xs), label = "f2") +plot!(xs, 4 * ones(length(xs)), label = nothing) + +import Clarabel +solver = Clarabel.Optimizer + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +model4 = solve(4) +nothing # hide + +model5 = solve(5) +nothing # hide + +model7 = solve(7) +nothing # hide + +ν7 = moment_matrix(model7[:c]) +η = atomic_measure(ν7, 1e-3) # Returns nothing as the dual is not atomic + +x_opt = η.atoms[1].center +p(x_opt) + +scatter!([x_opt[1]], [x_opt[2]], markershape = :star, label = nothing) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/min_univariate/b73294d5.svg b/previews/PR347/generated/Polynomial Optimization/min_univariate/b73294d5.svg new file mode 100644 index 000000000..e0f796c1b --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/min_univariate/b73294d5.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Polynomial Optimization/min_univariate/d43ebc73.svg b/previews/PR347/generated/Polynomial Optimization/min_univariate/d43ebc73.svg new file mode 100644 index 000000000..de1ac29da --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/min_univariate/d43ebc73.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Polynomial Optimization/min_univariate/index.html b/previews/PR347/generated/Polynomial Optimization/min_univariate/index.html new file mode 100644 index 000000000..7eed21d54 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/min_univariate/index.html @@ -0,0 +1,223 @@ + +Maximizing as minimum · SumOfSquares

Maximizing as minimum

Adapted from: (Floudas et al., 1999; Section 4.10), (Laurent, 2008; Example 6.23) and (Lasserre, 2009; Table 5.1)

Introduction

Consider the polynomial optimization problem from (Floudas et al., 1999; Section 4.10) of minimizing the linear function $-x_1 - x_2$ over the basic semialgebraic set defined by the inequalities $x_2 \le 2x_1^4 - 8x_1^3 + 8x_1^2 + 2$, $x_2 \le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36$ and the box constraints $0 \le x_1 \le 3$ and $0 \le x_2 \le 4$,

using DynamicPolynomials
+@polyvar x[1:2]
+p = -sum(x)
+using SumOfSquares
+f1 = 2x[1]^4 - 8x[1]^3 + 8x[1]^2 + 2
+f2 = 4x[1]^4 - 32x[1]^3 + 88x[1]^2 - 96x[1] + 36
+K = @set x[1] >= 0 && x[1] <= 3 && x[2] >= 0 && x[2] <= 4 && x[2] <= f1 && x[2] <= f2
Basic semialgebraic Set defined by no equality
+6 inequalities
+ x[1] ≥ 0
+ 3 - x[1] ≥ 0
+ x[2] ≥ 0
+ 4 - x[2] ≥ 0
+ 2 - x[2] + 8*x[1]^2 - 8*x[1]^3 + 2*x[1]^4 ≥ 0
+ 36 - x[2] - 96*x[1] + 88*x[1]^2 - 32*x[1]^3 + 4*x[1]^4 ≥ 0
+

As we can observe below, the bounds on x[2] could be dropped and optimization problem is equivalent to the maximization of min(f1, f2) between 0 and 3.

xs = range(0, stop = 3, length = 100)
+using Plots
+plot(xs, f1.(xs), label = "f1")
+plot!(xs, f2.(xs), label = "f2")
+plot!(xs, 4 * ones(length(xs)), label = nothing)
Example block output

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import Clarabel
+solver = Clarabel.Optimizer
Clarabel.MOIwrapper.Optimizer

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.

function solve(d)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = K, maxdegree = d)
+    optimize!(model)
+    println(solution_summary(model))
+    return model
+end
solve (generic function with 1 method)

The first level of the hierarchy gives a lower bound of -7`

model4 = solve(4)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 31
+  constraints   = 40
+  nnz(P)        = 0
+  nnz(A)        = 73
+  cones (total) = 6
+    : Zero        = 1,  numel = 10
+    : PSDTriangle = 5,  numel = (6,6,6,6,6)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   1.2590e-01   1.2590e-01  8.33e-17  6.99e-01  6.62e-01  1.00e+00  1.51e+00   ------
+  1   4.8332e-01   5.0333e-01  2.00e-02  1.40e-01  9.41e-02  1.86e-01  3.32e-01  8.02e-01
+  2   1.3995e+00   1.5138e+00  8.17e-02  8.66e-02  2.59e-02  2.10e-01  1.08e-01  7.85e-01
+  3   2.7854e+00   2.9400e+00  5.55e-02  2.03e-02  3.36e-03  1.83e-01  1.58e-02  8.78e-01
+  4   4.0242e+00   4.2592e+00  5.84e-02  1.43e-02  1.34e-03  2.61e-01  7.20e-03  7.46e-01
+  5   5.4090e+00   5.5096e+00  1.86e-02  4.16e-03  3.04e-04  1.09e-01  1.81e-03  8.27e-01
+  6   6.2811e+00   6.3385e+00  9.13e-03  1.73e-03  1.07e-04  6.15e-02  6.79e-04  7.22e-01
+  7   6.9685e+00   6.9720e+00  5.12e-04  6.60e-05  3.84e-06  3.75e-03  2.52e-05  9.69e-01
+  8   6.9993e+00   6.9994e+00  1.29e-05  1.66e-06  9.63e-08  9.46e-05  6.33e-07  9.75e-01
+  9   7.0000e+00   7.0000e+00  3.48e-07  4.54e-08  2.62e-09  2.56e-06  1.72e-08  9.73e-01
+ 10   7.0000e+00   7.0000e+00  1.18e-08  1.56e-09  8.90e-11  8.65e-08  5.85e-10  9.66e-01
+ 11   7.0000e+00   7.0000e+00  2.34e-10  3.13e-11  1.84e-12  1.72e-09  1.17e-11  9.80e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 3.34ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -7.00000e+00
+  Dual objective value : -7.00000e+00
+
+* Work counters
+  Solve time (sec)   : 3.33638e-03
+  Barrier iterations : 11

The second level improves the lower bound

model5 = solve(5)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 108
+  constraints   = 128
+  nnz(P)        = 0
+  nnz(A)        = 266
+  cones (total) = 7
+    : Zero        = 1,  numel = 21
+    : Nonnegative = 1,  numel = 2
+    : PSDTriangle = 5,  numel = (21,21,21,21,21)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   2.8313e-01   2.8313e-01  0.00e+00  7.53e-01  6.03e-01  1.00e+00  1.82e+00   ------
+  1   5.4905e-01   5.6026e-01  1.12e-02  1.28e-01  7.06e-02  1.86e-01  4.16e-01  8.05e-01
+  2   1.0075e+00   1.0482e+00  4.04e-02  3.51e-02  1.22e-02  8.87e-02  1.08e-01  8.48e-01
+  3   1.7352e+00   1.7929e+00  3.33e-02  8.17e-03  1.68e-03  7.10e-02  1.55e-02  9.20e-01
+  4   2.2703e+00   2.3425e+00  3.18e-02  3.66e-03  5.84e-04  7.97e-02  4.20e-03  8.20e-01
+  5   2.5204e+00   2.5826e+00  2.47e-02  2.51e-03  3.63e-04  6.81e-02  2.42e-03  6.21e-01
+  6   3.3688e+00   3.4392e+00  2.09e-02  6.50e-04  6.62e-05  7.25e-02  3.73e-04  8.78e-01
+  7   4.1613e+00   4.2336e+00  1.74e-02  3.75e-04  2.25e-05  7.36e-02  1.14e-04  8.80e-01
+  8   4.9013e+00   4.9482e+00  9.56e-03  1.66e-04  8.18e-06  4.76e-02  4.21e-05  8.78e-01
+  9   5.7265e+00   5.7548e+00  4.95e-03  6.35e-05  2.06e-06  2.86e-02  1.12e-05  8.50e-01
+ 10   5.7843e+00   5.8135e+00  5.04e-03  6.09e-05  1.89e-06  2.95e-02  1.03e-05  2.28e-01
+ 11   6.4423e+00   6.4536e+00  1.75e-03  1.28e-05  3.67e-07  1.13e-02  2.07e-06  8.34e-01
+ 12   6.6492e+00   6.6500e+00  1.19e-04  7.56e-07  2.24e-08  7.94e-04  1.26e-07  9.69e-01
+ 13   6.6662e+00   6.6663e+00  3.10e-06  1.97e-08  5.83e-10  2.08e-05  3.28e-09  9.74e-01
+ 14   6.6667e+00   6.6667e+00  8.84e-08  5.65e-10  1.66e-11  5.93e-07  9.36e-11  9.72e-01
+ 15   6.6667e+00   6.6667e+00  2.63e-09  1.69e-11  4.96e-13  1.76e-08  2.79e-12  9.70e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 26.8ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -6.66667e+00
+  Dual objective value : -6.66667e+00
+
+* Work counters
+  Solve time (sec)   : 2.67747e-02
+  Barrier iterations : 15

The third level finds the optimal objective value as lower bound...

model7 = solve(7)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 288
+  constraints   = 323
+  nnz(P)        = 0
+  nnz(A)        = 739
+  cones (total) = 8
+    : Zero        = 1,  numel = 36
+    : PSDTriangle = 7,  numel = (55,55,55,55,...,55)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   3.3234e-01   3.3234e-01  2.22e-16  7.75e-01  7.03e-01  1.00e+00  1.51e+00   ------
+  1   4.7370e-01   4.8104e-01  7.34e-03  1.20e-01  7.54e-02  1.77e-01  3.55e-01  8.03e-01
+  2   7.3313e-01   7.6805e-01  3.49e-02  4.16e-02  1.96e-02  1.12e-01  1.54e-01  7.48e-01
+  3   1.1439e+00   1.1684e+00  2.14e-02  7.53e-03  2.35e-03  4.09e-02  2.71e-02  8.65e-01
+  4   1.5684e+00   1.6151e+00  2.98e-02  3.00e-03  6.64e-04  5.81e-02  7.91e-03  8.51e-01
+  5   1.8613e+00   1.8904e+00  1.57e-02  1.41e-03  2.53e-04  3.50e-02  3.10e-03  6.74e-01
+  6   2.1699e+00   2.1913e+00  9.85e-03  5.14e-04  7.66e-05  2.40e-02  8.88e-04  8.03e-01
+  7   2.5021e+00   2.5220e+00  7.93e-03  1.85e-04  2.34e-05  2.11e-02  2.37e-04  8.01e-01
+  8   2.7896e+00   2.8141e+00  8.76e-03  1.17e-04  1.10e-05  2.54e-02  9.20e-05  8.08e-01
+  9   3.2619e+00   3.2812e+00  5.91e-03  3.96e-05  2.84e-06  1.96e-02  2.16e-05  7.88e-01
+ 10   3.6591e+00   3.6805e+00  5.86e-03  2.80e-05  1.09e-06  2.17e-02  7.16e-06  9.60e-01
+ 11   4.0143e+00   4.0278e+00  3.36e-03  1.31e-05  4.96e-07  1.36e-02  3.07e-06  7.92e-01
+ 12   4.3776e+00   4.3897e+00  2.76e-03  7.68e-06  2.25e-07  1.22e-02  1.31e-06  6.54e-01
+ 13   4.8717e+00   4.8798e+00  1.67e-03  2.67e-06  6.42e-08  8.16e-03  3.48e-07  8.11e-01
+ 14   5.0064e+00   5.0151e+00  1.74e-03  2.22e-06  4.55e-08  8.76e-03  2.29e-07  5.98e-01
+ 15   5.3203e+00   5.3231e+00  5.17e-04  6.99e-07  1.36e-08  2.76e-03  6.96e-08  9.90e-01
+ 16   5.4810e+00   5.4813e+00  6.57e-05  1.07e-07  2.07e-09  3.62e-04  9.89e-09  8.52e-01
+ 17   5.5042e+00   5.5043e+00  1.24e-05  1.45e-08  2.83e-10  6.85e-05  1.36e-09  9.58e-01
+ 18   5.5078e+00   5.5078e+00  6.98e-07  8.14e-10  1.59e-11  3.86e-06  7.64e-11  9.44e-01
+ 19   5.5080e+00   5.5080e+00  5.33e-08  5.62e-11  1.10e-12  2.94e-07  5.30e-12  9.84e-01
+ 20   5.5080e+00   5.5080e+00  1.09e-09  1.63e-12  2.93e-14  6.04e-09  1.09e-13  9.79e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 34.9ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -5.50801e+00
+  Dual objective value : -5.50801e+00
+
+* Work counters
+  Solve time (sec)   : 3.48859e-02
+  Barrier iterations : 20

...and proves it by exhibiting the minimizer.

ν7 = moment_matrix(model7[:c])
+η = atomic_measure(ν7, 1e-3) # Returns nothing as the dual is not atomic
Atomic measure on the variables x[1], x[2] with 1 atoms:
+ at [2.329520151218628, 3.178493153833861] with weight 0.9999999590079649

We can indeed verify that the objective value at x_opt is equal to the lower bound.

x_opt = η.atoms[1].center
+p(x_opt)
-5.508013305052489

We can see visualize the solution as follows:

scatter!([x_opt[1]], [x_opt[2]], markershape = :star, label = nothing)
Example block output

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/polynomial_optimization.ipynb b/previews/PR347/generated/Polynomial Optimization/polynomial_optimization.ipynb new file mode 100644 index 000000000..48fc7c092 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/polynomial_optimization.ipynb @@ -0,0 +1,1207 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Polynomial Optimization" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Contributed by**: Benoît Legat" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the polynomial optimization problem [Lasserre2009; Example 2.2](@cite) of\n", + "minimizing the polynomial $x^3 - x^2 + 2xy - y^2 + y^3$\n", + "over the polyhedron defined by the inequalities $x \\ge 0, y \\ge 0$ and $x + y \\geq 1$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(0, 1//4, 0)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x y\n", + "p = x^3 - x^2 + 2x*y -y^2 + y^3\n", + "using SumOfSquares\n", + "S = @set x >= 0 && y >= 0 && x + y >= 1\n", + "p(x=>1, y=>0), p(x=>1//2, y=>1//2), p(x=>0, y=>1)" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "## Local search" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "A local solver only uses the **local** information given by the the value, gradient and hessian\n", + "of the objective function and constraints at a given solution. When it converges, it therefore only\n", + "guarantees that the found solution is a **local** minimum.\n", + "In this example, the optimal solutions are $(x, y) = (1, 0)$ and $(x, y) = (0, 1)$ with objective value $0$ but\n", + "[Ipopt](https://github.com/jump-dev/Ipopt.jl/) only finds the local minimum $(1/2, 1/2)$ with objective value $1/4$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 12 Ap: 9.00e-01 Pobj: -6.0000000e+00 Ad: 1.00e+00 Dobj: -6.0000000e+00 \n", + "Success: SDP solved\n", + "Primal objective value: -6.0000000e+00 \n", + "Dual objective value: -6.0000000e+00 \n", + "Relative primal infeasibility: 2.31e-10 \n", + "Relative dual infeasibility: 3.44e-11 \n", + "Real Relative Gap: 1.36e-09 \n", + "XZ Relative Gap: 1.48e-09 \n", + "DIMACS error measures: 2.52e-10 0.00e+00 5.85e-11 0.00e+00 1.36e-09 1.48e-09\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit https://github.com/coin-or/Ipopt\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.14.14, running with linear solver MUMPS 5.6.2.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 0\n", + "Number of nonzeros in inequality constraint Jacobian.: 2\n", + "Number of nonzeros in Lagrangian Hessian.............: 3\n", + "\n", + "Total number of variables............................: 2\n", + " variables with only lower bounds: 2\n", + " variables with lower and upper bounds: 0\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 0\n", + "Total number of inequality constraints...............: 1\n", + " inequality constraints with only lower bounds: 1\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 1.9999940e-06 9.80e-01 1.33e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 5.3716721e-05 9.40e-01 1.18e+00 -1.0 3.97e-01 - 3.23e-02 5.03e-02h 1\n", + " 2 2.8887051e-01 0.00e+00 4.87e+01 -1.0 4.95e-01 2.0 1.00e+00 1.00e+00f 1\n", + " 3 2.8997185e-01 0.00e+00 1.00e-06 -1.0 1.33e-03 - 1.00e+00 1.00e+00f 1\n", + " 4 2.8022658e-01 0.00e+00 3.97e-01 -2.5 1.19e-02 1.5 1.00e+00 1.00e+00f 1\n", + " 5 2.5585775e-01 0.00e+00 3.45e-01 -2.5 3.10e-02 1.0 1.00e+00 1.00e+00f 1\n", + " 6 2.5292585e-01 0.00e+00 1.16e-01 -2.5 1.03e-02 0.6 1.00e+00 3.73e-01f 2\n", + " 7 2.5283150e-01 0.00e+00 1.54e-04 -2.5 1.25e-04 0.1 1.00e+00 1.00e+00f 1\n", + " 8 2.5021392e-01 0.00e+00 1.14e-02 -3.8 3.48e-03 0.5 1.00e+00 1.00e+00f 1\n", + " 9 2.5014901e-01 0.00e+00 9.49e-05 -3.8 8.65e-05 0.0 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 2.5000198e-01 0.00e+00 5.74e-04 -5.7 1.96e-04 0.5 1.00e+00 1.00e+00f 1\n", + " 11 2.5000184e-01 0.00e+00 1.48e-06 -5.7 1.90e-07 0.9 1.00e+00 1.00e+00f 1\n", + " 12 2.5000000e-01 0.00e+00 6.39e-06 -8.6 2.46e-06 0.4 1.00e+00 1.00e+00f 1\n", + " 13 2.5000000e-01 0.00e+00 1.67e-10 -8.6 2.41e-11 0.8 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 13\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 2.4999999500590342e-01 2.4999999500590342e-01\n", + "Dual infeasibility......: 1.6744750030994737e-10 1.6744750030994737e-10\n", + "Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 2.5059035596801718e-09 2.5059035596801718e-09\n", + "Overall NLP error.......: 2.5059035596801718e-09 2.5059035596801718e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 19\n", + "Number of objective gradient evaluations = 14\n", + "Number of equality constraint evaluations = 0\n", + "Number of inequality constraint evaluations = 19\n", + "Number of equality constraint Jacobian evaluations = 0\n", + "Number of inequality constraint Jacobian evaluations = 1\n", + "Number of Lagrangian Hessian evaluations = 13\n", + "Total seconds in IPOPT = 0.081\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "cell_type": "code", + "source": [ + "import Ipopt\n", + "model = Model(Ipopt.Optimizer)\n", + "@variable(model, a >= 0)\n", + "@variable(model, b >= 0)\n", + "@constraint(model, a + b >= 1)\n", + "@NLobjective(model, Min, a^3 - a^2 + 2a*b - b^2 + b^3)\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "As we can see below, the termination status is `LOCALLY_SOLVED` and not of `OPTIMAL`\n", + "because Ipopt only guarantees **local** optimality." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Ipopt\n\n* Status\n Result count : 1\n Termination status : LOCALLY_SOLVED\n Message from the solver:\n \"Solve_Succeeded\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 2.50000e-01\n Dual objective value : 7.50000e-01\n\n* Work counters\n Solve time (sec) : 8.20980e-02\n Barrier iterations : 13\n" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Indeed, the solution found is not globally optimal:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(0.49999999667062867, 0.4999999966705758)" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "value(a), value(b)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Note that the problem can be written equivalently as follows using [registered functions](https://jump.dev/JuMP.jl/stable/manual/nlp/#Register-a-function).\n", + "The difference is that the gradient and hessian will be computed via the *Symbolic Differentiation* provided\n", + "by MultivariatePolynomials instead of JuMP's *Automatic Differentiation*:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This is Ipopt version 3.14.14, running with linear solver MUMPS 5.6.2.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 0\n", + "Number of nonzeros in inequality constraint Jacobian.: 2\n", + "Number of nonzeros in Lagrangian Hessian.............: 3\n", + "\n", + "Total number of variables............................: 2\n", + " variables with only lower bounds: 2\n", + " variables with lower and upper bounds: 0\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 0\n", + "Total number of inequality constraints...............: 1\n", + " inequality constraints with only lower bounds: 1\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 1.9999940e-06 9.80e-01 1.33e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 5.3716721e-05 9.40e-01 1.18e+00 -1.0 3.97e-01 - 3.23e-02 5.03e-02h 1\n", + " 2 2.8887051e-01 0.00e+00 4.87e+01 -1.0 4.95e-01 2.0 1.00e+00 1.00e+00f 1\n", + " 3 2.8997185e-01 0.00e+00 1.00e-06 -1.0 1.33e-03 - 1.00e+00 1.00e+00f 1\n", + " 4 2.8022658e-01 0.00e+00 3.97e-01 -2.5 1.19e-02 1.5 1.00e+00 1.00e+00f 1\n", + " 5 2.5585775e-01 0.00e+00 3.45e-01 -2.5 3.10e-02 1.0 1.00e+00 1.00e+00f 1\n", + " 6 2.5292585e-01 0.00e+00 1.16e-01 -2.5 1.03e-02 0.6 1.00e+00 3.73e-01f 2\n", + " 7 2.5283150e-01 0.00e+00 1.54e-04 -2.5 1.25e-04 0.1 1.00e+00 1.00e+00f 1\n", + " 8 2.5021392e-01 0.00e+00 1.14e-02 -3.8 3.48e-03 0.5 1.00e+00 1.00e+00f 1\n", + " 9 2.5014901e-01 0.00e+00 9.49e-05 -3.8 8.65e-05 0.0 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 2.5000198e-01 0.00e+00 5.74e-04 -5.7 1.96e-04 0.5 1.00e+00 1.00e+00f 1\n", + " 11 2.5000184e-01 0.00e+00 1.48e-06 -5.7 1.90e-07 0.9 1.00e+00 1.00e+00f 1\n", + " 12 2.5000000e-01 0.00e+00 6.39e-06 -8.6 2.46e-06 0.4 1.00e+00 1.00e+00f 1\n", + " 13 2.5000000e-01 0.00e+00 1.67e-10 -8.6 2.41e-11 0.8 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 13\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 2.4999999500590339e-01 2.4999999500590339e-01\n", + "Dual infeasibility......: 1.6744750030994737e-10 1.6744750030994737e-10\n", + "Constraint violation....: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 2.5059035596801718e-09 2.5059035596801718e-09\n", + "Overall NLP error.......: 2.5059035596801718e-09 2.5059035596801718e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 19\n", + "Number of objective gradient evaluations = 14\n", + "Number of equality constraint evaluations = 0\n", + "Number of inequality constraint evaluations = 19\n", + "Number of equality constraint Jacobian evaluations = 0\n", + "Number of inequality constraint Jacobian evaluations = 1\n", + "Number of Lagrangian Hessian evaluations = 13\n", + "Total seconds in IPOPT = 0.079\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "cell_type": "code", + "source": [ + "f(a, b) = p(x => a, y => b)\n", + "∇p = differentiate(p, [x, y])\n", + "function ∇f(g, a, b)\n", + " for i in eachindex(g)\n", + " g[i] = ∇p[i](x => a, y => b)\n", + " end\n", + "end\n", + "∇²p = differentiate(∇p, [x, y])\n", + "function ∇²f(H, a, b)\n", + " for j in axes(∇²p, 2)\n", + " for i in j:size(∇²p, 1)\n", + " H[i, j] = ∇²p[i, j](x => a, y => b)\n", + " end\n", + " end\n", + "end\n", + "using Ipopt\n", + "gmodel = Model(Ipopt.Optimizer)\n", + "@variable(gmodel, a >= 0)\n", + "@variable(gmodel, b >= 0)\n", + "@constraint(gmodel, a + b >= 1)\n", + "register(gmodel, :f, 2, f, ∇f, ∇²f)\n", + "@NLobjective(gmodel, Min, f(a, b))\n", + "optimize!(gmodel)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Even if we have the algebraic expressions of gradient and hessian,\n", + "Ipopt is not using these symbolic expressions but only local information\n", + "hence it can still only provide local guarantees:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Ipopt\n\n* Status\n Result count : 1\n Termination status : LOCALLY_SOLVED\n Message from the solver:\n \"Solve_Succeeded\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 2.50000e-01\n Dual objective value : 7.50000e-01\n\n* Work counters\n Solve time (sec) : 8.00009e-02\n Barrier iterations : 13\n" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(gmodel)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "and the same solution is found:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(0.49999999667062867, 0.4999999966705758)" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "value(a), value(b)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "## Sum-of-Squares approach" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "#11 (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "import SCS\n", + "scs = SCS.Optimizer\n", + "import Dualization\n", + "dual_scs = Dualization.dual_optimizer(scs)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following program searches for the largest lower bound and finds zero." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 10, constraints m: 25\n", + "cones: \t z: primal zero / dual free vars: 1\n", + "\t s: psd vars: 24, ssize: 4\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 37, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 1.90e+01 1.01e+00 5.26e+01 -2.61e+01 1.00e-01 1.79e-04 \n", + " 125| 4.27e-05 3.97e-05 9.70e-06 8.12e-06 8.63e-01 1.19e-03 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 1.19e-03s = setup: 7.39e-05s + solve: 1.11e-03s\n", + "\t lin-sys: 7.45e-05s, cones: 8.77e-04s, accel: 7.78e-06s\n", + "------------------------------------------------------------------\n", + "objective = 0.000008\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(dual_scs)\n", + "@variable(model, α)\n", + "@objective(model, Max, α)\n", + "@constraint(model, c3, p >= α, domain = S)\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "This time, the termination status is `OPTIMAL` but this does not necessarily mean that we found\n", + "the optimal solution to the polynomial optimization problem.\n", + "This only means that CSDP founds an optimal solution to the Sum-of-Squares relaxation." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Dual model with SCS attached\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"solved\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 1.29679e-05\n Dual objective value : 3.27176e-06\n\n* Work counters\n Solve time (sec) : 1.18694e-03\n" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "The feasibility of the primal solution guarantees that the objective value `0` is a lower bound\n", + "to the polynomial optimization problem.\n", + "The optimality means that it's the best lower bound we can get (at this degree of the hierarcy).\n", + "Using the solution $(1/2, 1/2)$ found by Ipopt of objective value $1/4$\n", + "and this certificate of lower bound $0$ we know that the optimal objective value is in the interval $[0, 1/4]$\n", + "but we still do not know what it is (if we consider that we did not try the solutions $(1, 0)$ and $(0, 1)$ as done in the introduction).\n", + "If the dual of the constraint `c3` was atomic, its atoms would have given optimal solutions of objective value $0$ but that is not the case." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "ν3 = moment_matrix(c3)\n", + "atomic_measure(ν3, 1e-3) # Returns nothing as the dual is not atomic" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "Fortunately, there is a hierarchy of programs with increasingly better bounds that can be solved until we get one with atom dual variables.\n", + "This comes from the way the Sum-of-Squares constraint with domain `S` is formulated.\n", + "The polynomial $p - \\alpha$ is guaranteed to be nonnegative over the domain `S` if there exists Sum-of-Squares polynomials $s_0$, $s_1$, $s_2$, $s_3$ such that\n", + "$$\n", + "p - \\alpha = s_0 + s_1 x + s_2 y + s_3 (x + y - 1).\n", + "$$\n", + "Indeed, in the domain `S`, $x$, $y$ and $x + y - 1$ are nonnegative so the right-hand side is a sum of squares hence is nonnegative.\n", + "Once the degrees of $s_1$, $s_2$ and $s_3$ have been decided, the degree needed for $s_0$ will be determined but we have a freedom in choosing the degrees of $s_1$, $s_2$ and $s_3$.\n", + "By default, they are chosen so that the degrees of $s_1 x$, $s_2 y$ and $s_3 (x + y - 1)$ match those of $p - \\alpha$ but this can be overwritten using the `maxdegree` keyword argument." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "### The maxdegree keyword argument" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The maximum total degree (i.e. maximum sum of the exponents of $x$ and $y$) of the monomials of $p$ is 3 so the constraint in the program above is equivalent to `@constraint(model, p >= α, domain = S, maxdegree = 3)`.\n", + "That is, since $x$, $y$ and $x + y - 1$ have total degree 1, the sum of squares polynomials $s_1$, $s_2$ and $s_3$ have been chosen with maximum total degree $2$.\n", + "Since these polynomials are sums of squares, their degree must be even so the next maximum total degree to try is 4.\n", + "For this reason, the keywords `maxdegree = 4` and `maxdegree = 5` have the same effect in this example.\n", + "In general, if the polynomials in the domain are not all odd or all even, each value of `maxdegree` has a different effect in the choice of the maximum total degree of some $s_i$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 10, constraints m: 25\n", + "cones: \t z: primal zero / dual free vars: 1\n", + "\t s: psd vars: 24, ssize: 4\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 37, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 1.90e+01 1.01e+00 5.26e+01 -2.61e+01 1.00e-01 3.04e-03 \n", + " 125| 4.27e-05 3.97e-05 9.70e-06 8.12e-06 8.63e-01 1.38e-02 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 1.38e-02s = setup: 7.45e-05s + solve: 1.37e-02s\n", + "\t lin-sys: 7.65e-05s, cones: 8.90e-04s, accel: 8.78e-06s\n", + "------------------------------------------------------------------\n", + "objective = 0.000008\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model = SOSModel(dual_scs)\n", + "@variable(model, α)\n", + "@objective(model, Max, α)\n", + "@constraint(model, c4, p >= α, domain = S, maxdegree = 4)\n", + "optimize!(model)" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "We can see that the basis of the moment matrix didn't increase:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MomentMatrix with row/column basis:\n MonomialBasis([1, y, x])\nAnd entries in a 3×3 SymMatrix{Float64}:\n 0.9999988622359888 0.4999978058971253 0.499997805897121\n 0.4999978058971253 0.49992054531120933 7.563537032711307e-5\n 0.499997805897121 7.563537032711307e-5 0.49992054531120506" + }, + "metadata": {}, + "execution_count": 13 + } + ], + "cell_type": "code", + "source": [ + "moment_matrix(c4)" + ], + "metadata": {}, + "execution_count": 13 + }, + { + "cell_type": "markdown", + "source": [ + "This is because of the Newton polytope reduction that determined that gram matrix will\n", + "be zero for these degrees so it reduced the problem back to the equivalent of `maxdegree` 3\n", + "Let's turn this off with `newton_polytope = nothing`" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 15, constraints m: 40\n", + "cones: \t z: primal zero / dual free vars: 1\n", + "\t s: psd vars: 39, ssize: 4\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 52, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 1.06e+01 4.30e-01 3.19e+01 -1.57e+01 1.00e-01 1.99e-04 \n", + " 125| 2.44e-04 2.14e-05 1.20e-05 -4.90e-05 1.00e-01 1.74e-03 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 1.74e-03s = setup: 8.15e-05s + solve: 1.66e-03s\n", + "\t lin-sys: 1.09e-04s, cones: 1.33e-03s, accel: 5.09e-05s\n", + "------------------------------------------------------------------\n", + "objective = -0.000049\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "function sos(solver, deg)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = S, maxdegree = deg, newton_polytope = nothing)\n", + " optimize!(model)\n", + " return model\n", + "end\n", + "dual_model4 = sos(dual_scs, 4)\n", + "nothing #hide" + ], + "metadata": {}, + "execution_count": 14 + }, + { + "cell_type": "markdown", + "source": [ + "We see that the lower bound is still 0:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : Dual model with SCS attached\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"solved\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : -4.29823e-05\n Dual objective value : -5.49868e-05\n\n* Work counters\n Solve time (sec) : 1.74135e-03\n" + }, + "metadata": {}, + "execution_count": 15 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(dual_model4)" + ], + "metadata": {}, + "execution_count": 15 + }, + { + "cell_type": "markdown", + "source": [ + "Let's now look at which solution we can extract from the moment matrix:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MomentMatrix with row/column basis:\n MonomialBasis([1, y, x, y^2, x*y, x^2])\nAnd entries in a 6×6 SymMatrix{Float64}:\n 1.0000084649794703 0.5001118271563997 … 0.5003336181951755\n 0.5001118271563997 0.5003460975047918 -8.014565847567821e-5\n 0.500111827156376 -0.00012664913632054993 0.5004463755227944\n 0.5003336181952008 0.5004463755228222 1.952914136044233\n -0.00012729223307204044 -9.194362986274147e-5 -1.8561449853462841\n 0.5003336181951755 -8.014565847567821e-5 … 8.524707147814647" + }, + "metadata": {}, + "execution_count": 16 + } + ], + "cell_type": "code", + "source": [ + "dual_ν4 = moment_matrix(dual_model4[:c])" + ], + "metadata": {}, + "execution_count": 16 + }, + { + "cell_type": "markdown", + "source": [ + "Looking at the singular values, `4` seems to be a reasonable rank:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "6-element Vector{Float64}:\n 11.292137082084412\n 6.612780281630687\n 1.578866177150388\n 1.0597600660608397\n 0.45948547678078755\n 3.371754857737788e-16" + }, + "metadata": {}, + "execution_count": 17 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra\n", + "svdvals(Matrix(dual_ν4.Q))" + ], + "metadata": {}, + "execution_count": 17 + }, + { + "cell_type": "markdown", + "source": [ + "The solution we extract is `(0.5, 0.5)` which is the solution found by Ipopt:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Atomic measure on the variables x, y with 1 atoms:\n at [0.5000778765242692, 0.5001018243812855] with weight 1.6079422332661" + }, + "metadata": {}, + "execution_count": 18 + } + ], + "cell_type": "code", + "source": [ + "atomic_measure(dual_ν4, FixedRank(4))" + ], + "metadata": {}, + "execution_count": 18 + }, + { + "cell_type": "markdown", + "source": [ + "This process is quite sensitive numerically so let's try to solve it without dualization as well:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "------------------------------------------------------------------\n", + "\t SCS v3.2.4 - Splitting Conic Solver\n", + "\t(c) Brendan O'Donoghue, Stanford University, 2012\n", + "------------------------------------------------------------------\n", + "problem: variables n: 40, constraints m: 54\n", + "cones: \t z: primal zero / dual free vars: 15\n", + "\t s: psd vars: 39, ssize: 4\n", + "settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07\n", + "\t alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1\n", + "\t max_iters: 100000, normalize: 1, rho_x: 1.00e-06\n", + "\t acceleration_lookback: 10, acceleration_interval: 10\n", + "\t compiled with openmp parallelization enabled\n", + "lin-sys: sparse-direct-amd-qdldl\n", + "\t nnz(A): 91, nnz(P): 0\n", + "------------------------------------------------------------------\n", + " iter | pri res | dua res | gap | obj | scale | time (s)\n", + "------------------------------------------------------------------\n", + " 0| 2.21e+01 1.35e+00 3.74e+01 -1.86e+01 1.00e-01 2.51e-04 \n", + " 175| 7.26e-05 8.28e-06 2.10e-05 -1.57e-05 1.00e-01 2.51e-03 \n", + "------------------------------------------------------------------\n", + "status: solved\n", + "timings: total: 2.51e-03s = setup: 1.30e-04s + solve: 2.38e-03s\n", + "\t lin-sys: 2.43e-04s, cones: 1.84e-03s, accel: 5.95e-05s\n", + "------------------------------------------------------------------\n", + "objective = -0.000016\n", + "------------------------------------------------------------------\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model4 = sos(scs, 4)\n", + "nothing #hide" + ], + "metadata": {}, + "execution_count": 19 + }, + { + "cell_type": "markdown", + "source": [ + "We see that the lower bound is again 0:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : SCS\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"solved\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 2.61826e-05\n Dual objective value : 5.20758e-06\n\n* Work counters\n Solve time (sec) : 2.51293e-03\n" + }, + "metadata": {}, + "execution_count": 20 + } + ], + "cell_type": "code", + "source": [ + "solution_summary(model4)" + ], + "metadata": {}, + "execution_count": 20 + }, + { + "cell_type": "markdown", + "source": [ + "The moment matrix is the following" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MomentMatrix with row/column basis:\n MonomialBasis([1, y, x, y^2, x*y, x^2])\nAnd entries in a 6×6 SymMatrix{Float64}:\n 1.0000007181476624 0.49999933411667535 … 0.499983379029577\n 0.49999933411667535 0.4999834837556788 8.47685915114403e-6\n 0.4999993341166765 1.482541592461203e-5 0.49997241665096603\n 0.4999833790295761 0.4999724166509653 0.26228006757487266\n 1.5473299881402495e-5 7.379233003906931e-6 0.25448530696921917\n 0.499983379029577 8.47685915114403e-6 … 0.796825700565282" + }, + "metadata": {}, + "execution_count": 21 + } + ], + "cell_type": "code", + "source": [ + "ν4 = moment_matrix(model4[:c])" + ], + "metadata": {}, + "execution_count": 21 + }, + { + "cell_type": "markdown", + "source": [ + "Looking at the singular values, `3` seems to be a reasonable rank:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "6-element Vector{Float64}:\n 2.1989525826317653\n 1.0175199095063976\n 0.6030514893217399\n 0.019380459836853832\n 0.016994381823767828\n 5.714524905397067e-16" + }, + "metadata": {}, + "execution_count": 22 + } + ], + "cell_type": "code", + "source": [ + "svdvals(Matrix(ν4.Q))" + ], + "metadata": {}, + "execution_count": 22 + }, + { + "cell_type": "markdown", + "source": [ + "This time, the dual variable is atomic as it is the moments of the measure\n", + "$$0.5 \\delta(x-1, y) + 0.5 \\delta(x, y-1)$$\n", + "where $\\delta(x, y)$ is the dirac measure centered at $(0, 0)$.\n", + "Therefore the program provides both a certificate that $0$ is a lower bound and a certificate that it is also an upper bound since it is attained at the global minimizers $(1, 0)$ and $(0, 1)$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Atomic measure on the variables x, y with 2 atoms:\n at [0.9946508364409347, 0.005346125382870444] with weight 0.5511753483416838\n at [-0.011834484693469205, 1.011831446517274] with weight 0.5285747070034253" + }, + "metadata": {}, + "execution_count": 23 + } + ], + "cell_type": "code", + "source": [ + "atomic_measure(ν4, FixedRank(3))" + ], + "metadata": {}, + "execution_count": 23 + }, + { + "cell_type": "markdown", + "source": [ + "## A deeper look into atom extraction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The moment matrix is transformed into a system of polynomials equations whose solutions give the atoms.\n", + "This transformation uses the SVD decomposition of the moment matrix and discards the equations corresponding to the lowest singular values.\n", + "When this system of equation has an infinite number of solutions, `atomic_measure` concludes that the measure is not atomic.\n", + "For instance, with `maxdegree = 3`, we obtain the system\n", + "$$x + y = 1$$\n", + "which contains a whole line of solution.\n", + "This explains `atomic_measure` returned `nothing`." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "ν3 = moment_matrix(c3)\n", + "SumOfSquares.MultivariateMoments.compute_support!(ν3, LeadingRelativeRankTol(1e-3))" + ], + "metadata": {}, + "execution_count": 24 + }, + { + "cell_type": "markdown", + "source": [ + "With `maxdegree = 4`, we obtain the system\n", + "$$\n", + "\\begin{aligned}\n", + " x + y & = 1\\\\\n", + " y^2 & = y\\\\\n", + " xy & = 0\\\\\n", + " -y + y^2 - x*y & = 0\n", + " y^2 - 2y + 1 & = x^2\n", + "\\end{aligned}\n", + "$$" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "ν4 = moment_matrix(model4[:c])\n", + "SumOfSquares.MultivariateMoments.compute_support!(ν4, FixedRank(3))" + ], + "metadata": {}, + "execution_count": 25 + }, + { + "cell_type": "markdown", + "source": [ + "This system can be reduced to the equivalent system\n", + "$$\n", + "\\begin{aligned}\n", + " x + y & = 1\\\\\n", + " y^2 & = y\n", + "\\end{aligned}\n", + "$$\n", + "which has the solutions $(0, 1)$ and $(1, 0)$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Algebraic Set defined by 2 equalities\n -0.9999969618238052 + 1.0000000000000002*y + x = 0\n 0.005409377779409965 - 1.0171775719001446*y + y^2 = 0\n" + }, + "metadata": {}, + "execution_count": 26 + } + ], + "cell_type": "code", + "source": [ + "SemialgebraicSets.compute_gröbner_basis!(ideal(ν4.support))\n", + "ν4.support" + ], + "metadata": {}, + "execution_count": 26 + }, + { + "cell_type": "markdown", + "source": [ + "The solutions of this system then give the minimizers" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2-element Vector{Vector{Float64}}:\n [0.9946508364409377, 0.0053461253828677845]\n [-0.011834484693471814, 1.011831446517277]" + }, + "metadata": {}, + "execution_count": 27 + } + ], + "cell_type": "code", + "source": [ + "collect(ν4.support)" + ], + "metadata": {}, + "execution_count": 27 + }, + { + "cell_type": "markdown", + "source": [ + "The function `atomic_measure` then reuses the matrix of moments to find the weights $1/2$, $1/2$ corresponding to the diracs centered respectively at $(0, 1)$ and $(1, 0)$.\n", + "This details how the function obtained the result\n", + "$$0.5 \\delta(x-1, y) + 0.5 \\delta(x, y-1)$$\n", + "given in the previous section." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## HomotopyContinuation" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "As discussed in the previous section, the atom extraction relies on the solution\n", + "of a system of algebraic equations. The `atomic_measure` function takes an optional\n", + "`algebraic_solver` argument that is used to solve this system of equation.\n", + "If no solver is provided, the default solver of SemialgebraicSets.jl is used which\n", + "currently computes the Gröbner basis, then the multiplication matrices and\n", + "then the Schur decomposition of a random combination of these matrices.\n", + "As the system of equations is obtained from a numerical solution and is represented\n", + "using floating point coefficients, homotopy continuation is recommended as it is\n", + "more numerically robust than Gröbner basis computation.\n", + "The following uses homotopy continuation to solve the system of equations." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\rComputing mixed cells... 2 Time: 0:00:00\u001b[K\r\n", + " mixed_volume: 3\u001b[K\r\u001b[A\n", + "\r\u001b[K\u001b[A\rComputing mixed cells... 3 Time: 0:00:01\u001b[K\r\n", + " mixed_volume: 4\u001b[K\n", + "\rTracking 4 paths... 50%|███████████████▌ | ETA: 0:00:19\u001b[K\r\n", + " # paths tracked: 2\u001b[K\r\n", + " # non-singular solutions (real): 0 (0)\u001b[K\r\n", + " # singular endpoints (real): 0 (0)\u001b[K\r\n", + " # total solutions (real): 0 (0)\u001b[K\r\u001b[A\r\u001b[A\r\u001b[A\r\u001b[A\n", + "\n", + "\n", + "\n", + "\r\u001b[K\u001b[A\r\u001b[K\u001b[A\r\u001b[K\u001b[A\r\u001b[K\u001b[A\rTracking 4 paths... 100%|███████████████████████████████| Time: 0:00:19\u001b[K\r\n", + " # paths tracked: 4\u001b[K\r\n", + " # non-singular solutions (real): 0 (0)\u001b[K\r\n", + " # singular endpoints (real): 0 (0)\u001b[K\r\n", + " # total solutions (real): 0 (0)\u001b[K\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Atomic measure on the variables x, y with 2 atoms:\n at [-0.007878353532467358, 1.0220511100153338] with weight 0.5196924593421036\n at [1.002211889406058, 0.007419290990418704] with weight 0.5449237097532689" + }, + "metadata": {}, + "execution_count": 28 + } + ], + "cell_type": "code", + "source": [ + "using HomotopyContinuation\n", + "algebraic_solver = SemialgebraicSetsHCSolver(; excess_residual_tol = 1e-1, real_tol = 1e-1, compile = false)\n", + "atomic_measure(ν4, FixedRank(3), Echelon(), algebraic_solver)" + ], + "metadata": {}, + "execution_count": 28 + }, + { + "cell_type": "markdown", + "source": [ + "As the system has 3 equations for 2 variables and the coefficients of the equations\n", + "are to be treated with tolerance since they originate from the solution of an SDP,\n", + "we need to set `excess_residual_tol` and `real_tol` to a high tolerance otherwise,\n", + "HomotopyContinuation would consider that there is no solution.\n", + "Indeed, as the system is overdetermined (it has more equations than variables)\n", + "HomotopyContinuation expects to have excess solution hence it filters out\n", + "excess solution among the solution found. It determines which solution are in excess\n", + "by comparing the infinity norm of the residuals of the equations at the solution with `excess_residual_tol`.\n", + "It also filters out solution for which the absolute value of the imaginary part of one of the entry\n", + "is larger than `real_tol` and strips out the imaginary part.\n", + "The raw solutions obtained by HomotopyContinuation can be obtained as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\rTracking 4 paths... 50%|███████████████▌ | ETA: 0:00:04\u001b[K\r\n", + " # paths tracked: 2\u001b[K\r\n", + " # non-singular solutions (real): 0 (0)\u001b[K\r\n", + " # singular endpoints (real): 0 (0)\u001b[K\r\n", + " # total solutions (real): 0 (0)\u001b[K\r\u001b[A\r\u001b[A\r\u001b[A\r\u001b[A\n", + "\n", + "\n", + "\n", + "\r\u001b[K\u001b[A\r\u001b[K\u001b[A\r\u001b[K\u001b[A\r\u001b[K\u001b[A\rTracking 4 paths... 100%|███████████████████████████████| Time: 0:00:04\u001b[K\r\n", + " # paths tracked: 4\u001b[K\r\n", + " # non-singular solutions (real): 0 (0)\u001b[K\r\n", + " # singular endpoints (real): 0 (0)\u001b[K\r\n", + " # total solutions (real): 0 (0)\u001b[K\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "4-element Vector{HomotopyContinuation.PathResult}:\n PathResult:\n • return_code → :excess_solution\n • solution → ComplexF64[-0.041634086203944605 - 0.01810222691184391im, 0.9908741267814762 + 0.033511473116853874im]\n • accuracy → 0.053044\n • residual → 0.039395\n • condition_jacobian → 12.701\n • steps → 21 / 0\n • extended_precision → false\n • path_number → 1\n\n PathResult:\n • return_code → :excess_solution\n • solution → ComplexF64[-0.5421132694621764 + 0.23568311583954657im, 1.105649362134117 + 0.453926434237157im]\n • accuracy → 0.81612\n • residual → 0.47627\n • condition_jacobian → 3.4228\n • steps → 40 / 0\n • extended_precision → false\n • path_number → 2\n\n PathResult:\n • return_code → :excess_solution\n • solution → ComplexF64[1.0078394482206643 - 0.007761877714847081im, 0.005167757390488504 + 0.006270800475229618im]\n • accuracy → 0.013095\n • residual → 0.0078213\n • condition_jacobian → 33.401\n • steps → 27 / 0\n • extended_precision → false\n • path_number → 3\n\n PathResult:\n • return_code → :excess_solution\n • solution → ComplexF64[7.011528784710424 + 46.77462338701359im, 8.689544757437224 + 47.05742436019803im]\n • accuracy → 94.977\n • residual → 28.929\n • condition_jacobian → 284.93\n • steps → 50 / 0\n • extended_precision → false\n • path_number → 4\n" + }, + "metadata": {}, + "execution_count": 29 + } + ], + "cell_type": "code", + "source": [ + "F = HomotopyContinuation.System(ν4.support)\n", + "res = HomotopyContinuation.solve(F, algebraic_solver.options...)\n", + "path_results(res)" + ], + "metadata": {}, + "execution_count": 29 + }, + { + "cell_type": "markdown", + "source": [ + "The printed `residual` above shows why `1e-1` allows to filter how the 2 actual\n", + "solutions from the 2 excess solutions." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/polynomial_optimization.jl b/previews/PR347/generated/Polynomial Optimization/polynomial_optimization.jl new file mode 100644 index 000000000..75522b856 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/polynomial_optimization.jl @@ -0,0 +1,122 @@ +using DynamicPolynomials +@polyvar x y +p = x^3 - x^2 + 2x*y -y^2 + y^3 +using SumOfSquares +S = @set x >= 0 && y >= 0 && x + y >= 1 +p(x=>1, y=>0), p(x=>1//2, y=>1//2), p(x=>0, y=>1) + +import Ipopt +model = Model(Ipopt.Optimizer) +@variable(model, a >= 0) +@variable(model, b >= 0) +@constraint(model, a + b >= 1) +@NLobjective(model, Min, a^3 - a^2 + 2a*b - b^2 + b^3) +optimize!(model) + +solution_summary(model) + +value(a), value(b) + +f(a, b) = p(x => a, y => b) +∇p = differentiate(p, [x, y]) +function ∇f(g, a, b) + for i in eachindex(g) + g[i] = ∇p[i](x => a, y => b) + end +end +∇²p = differentiate(∇p, [x, y]) +function ∇²f(H, a, b) + for j in axes(∇²p, 2) + for i in j:size(∇²p, 1) + H[i, j] = ∇²p[i, j](x => a, y => b) + end + end +end +using Ipopt +gmodel = Model(Ipopt.Optimizer) +@variable(gmodel, a >= 0) +@variable(gmodel, b >= 0) +@constraint(gmodel, a + b >= 1) +register(gmodel, :f, 2, f, ∇f, ∇²f) +@NLobjective(gmodel, Min, f(a, b)) +optimize!(gmodel) + +solution_summary(gmodel) + +value(a), value(b) + +import SCS +scs = SCS.Optimizer +import Dualization +dual_scs = Dualization.dual_optimizer(scs) + +model = SOSModel(dual_scs) +@variable(model, α) +@objective(model, Max, α) +@constraint(model, c3, p >= α, domain = S) +optimize!(model) + +solution_summary(model) + +ν3 = moment_matrix(c3) +atomic_measure(ν3, 1e-3) # Returns nothing as the dual is not atomic + +model = SOSModel(dual_scs) +@variable(model, α) +@objective(model, Max, α) +@constraint(model, c4, p >= α, domain = S, maxdegree = 4) +optimize!(model) + +moment_matrix(c4) + +function sos(solver, deg) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = S, maxdegree = deg, newton_polytope = nothing) + optimize!(model) + return model +end +dual_model4 = sos(dual_scs, 4) +nothing #hide + +solution_summary(dual_model4) + +dual_ν4 = moment_matrix(dual_model4[:c]) + +using LinearAlgebra +svdvals(Matrix(dual_ν4.Q)) + +atomic_measure(dual_ν4, FixedRank(4)) + +model4 = sos(scs, 4) +nothing #hide + +solution_summary(model4) + +ν4 = moment_matrix(model4[:c]) + +svdvals(Matrix(ν4.Q)) + +atomic_measure(ν4, FixedRank(3)) + +ν3 = moment_matrix(c3) +SumOfSquares.MultivariateMoments.compute_support!(ν3, LeadingRelativeRankTol(1e-3)) + +ν4 = moment_matrix(model4[:c]) +SumOfSquares.MultivariateMoments.compute_support!(ν4, FixedRank(3)) + +SemialgebraicSets.compute_gröbner_basis!(ideal(ν4.support)) +ν4.support + +collect(ν4.support) + +using HomotopyContinuation +algebraic_solver = SemialgebraicSetsHCSolver(; excess_residual_tol = 1e-1, real_tol = 1e-1, compile = false) +atomic_measure(ν4, FixedRank(3), Echelon(), algebraic_solver) + +F = HomotopyContinuation.System(ν4.support) +res = HomotopyContinuation.solve(F, algebraic_solver.options...) +path_results(res) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/polynomial_optimization/index.html b/previews/PR347/generated/Polynomial Optimization/polynomial_optimization/index.html new file mode 100644 index 000000000..8bea43ed3 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/polynomial_optimization/index.html @@ -0,0 +1,451 @@ + +Polynomial Optimization · SumOfSquares

Polynomial Optimization

Contributed by: Benoît Legat

Introduction

Consider the polynomial optimization problem (Lasserre, 2009; Example 2.2) of minimizing the polynomial $x^3 - x^2 + 2xy - y^2 + y^3$ over the polyhedron defined by the inequalities $x \ge 0, y \ge 0$ and $x + y \geq 1$.

using DynamicPolynomials
+@polyvar x y
+p = x^3 - x^2 + 2x*y -y^2 + y^3
+using SumOfSquares
+S = @set x >= 0 && y >= 0 && x + y >= 1
+p(x=>1, y=>0), p(x=>1//2, y=>1//2), p(x=>0, y=>1)
(0, 1//4, 0)

A local solver only uses the local information given by the the value, gradient and hessian of the objective function and constraints at a given solution. When it converges, it therefore only guarantees that the found solution is a local minimum. In this example, the optimal solutions are $(x, y) = (1, 0)$ and $(x, y) = (0, 1)$ with objective value $0$ but Ipopt only finds the local minimum $(1/2, 1/2)$ with objective value $1/4$.

import Ipopt
+model = Model(Ipopt.Optimizer)
+@variable(model, a >= 0)
+@variable(model, b >= 0)
+@constraint(model, a + b >= 1)
+@NLobjective(model, Min, a^3 - a^2 + 2a*b - b^2 + b^3)
+optimize!(model)
Success: SDP solved
+Primal objective value: 0.0000000e+00
+Dual objective value: 0.0000000e+00
+Relative primal infeasibility: 5.23e-17
+Relative dual infeasibility: 5.00e-11
+Real Relative Gap: 0.00e+00
+XZ Relative Gap: 1.00e-10
+DIMACS error measures: 7.85e-17 0.00e+00 5.00e-11 0.00e+00 0.00e+00 1.00e-10
+This is Ipopt version 3.14.14, running with linear solver MUMPS 5.6.2.
+
+Number of nonzeros in equality constraint Jacobian...:        0
+Number of nonzeros in inequality constraint Jacobian.:        2
+Number of nonzeros in Lagrangian Hessian.............:        3
+
+Total number of variables............................:        2
+                     variables with only lower bounds:        2
+                variables with lower and upper bounds:        0
+                     variables with only upper bounds:        0
+Total number of equality constraints.................:        0
+Total number of inequality constraints...............:        1
+        inequality constraints with only lower bounds:        1
+   inequality constraints with lower and upper bounds:        0
+        inequality constraints with only upper bounds:        0
+
+iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
+   0  1.9999940e-06 9.80e-01 1.33e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
+   1  5.3716721e-05 9.40e-01 1.18e+00  -1.0 3.97e-01    -  3.23e-02 5.03e-02h  1
+   2  2.8887051e-01 0.00e+00 4.87e+01  -1.0 4.95e-01   2.0 1.00e+00 1.00e+00f  1
+   3  2.8997185e-01 0.00e+00 1.00e-06  -1.0 1.33e-03    -  1.00e+00 1.00e+00f  1
+   4  2.8022658e-01 0.00e+00 3.97e-01  -2.5 1.19e-02   1.5 1.00e+00 1.00e+00f  1
+   5  2.5585775e-01 0.00e+00 3.45e-01  -2.5 3.10e-02   1.0 1.00e+00 1.00e+00f  1
+   6  2.5292585e-01 0.00e+00 1.16e-01  -2.5 1.03e-02   0.6 1.00e+00 3.73e-01f  2
+   7  2.5283150e-01 0.00e+00 1.54e-04  -2.5 1.25e-04   0.1 1.00e+00 1.00e+00f  1
+   8  2.5021392e-01 0.00e+00 1.14e-02  -3.8 3.48e-03   0.5 1.00e+00 1.00e+00f  1
+   9  2.5014901e-01 0.00e+00 9.49e-05  -3.8 8.65e-05   0.0 1.00e+00 1.00e+00f  1
+iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
+  10  2.5000198e-01 0.00e+00 5.74e-04  -5.7 1.96e-04   0.5 1.00e+00 1.00e+00f  1
+  11  2.5000184e-01 0.00e+00 1.48e-06  -5.7 1.90e-07   0.9 1.00e+00 1.00e+00f  1
+  12  2.5000000e-01 0.00e+00 6.39e-06  -8.6 2.46e-06   0.4 1.00e+00 1.00e+00f  1
+  13  2.5000000e-01 0.00e+00 1.67e-10  -8.6 2.41e-11   0.8 1.00e+00 1.00e+00h  1
+
+Number of Iterations....: 13
+
+                                   (scaled)                 (unscaled)
+Objective...............:   2.4999999500590342e-01    2.4999999500590342e-01
+Dual infeasibility......:   1.6744750030994737e-10    1.6744750030994737e-10
+Constraint violation....:   0.0000000000000000e+00    0.0000000000000000e+00
+Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
+Complementarity.........:   2.5059035596801718e-09    2.5059035596801718e-09
+Overall NLP error.......:   2.5059035596801718e-09    2.5059035596801718e-09
+
+
+Number of objective function evaluations             = 19
+Number of objective gradient evaluations             = 14
+Number of equality constraint evaluations            = 0
+Number of inequality constraint evaluations          = 19
+Number of equality constraint Jacobian evaluations   = 0
+Number of inequality constraint Jacobian evaluations = 1
+Number of Lagrangian Hessian evaluations             = 13
+Total seconds in IPOPT                               = 1.509
+
+EXIT: Optimal Solution Found.

As we can see below, the termination status is LOCALLY_SOLVED and not of OPTIMAL because Ipopt only guarantees local optimality.

solution_summary(model)
* Solver : Ipopt
+
+* Status
+  Result count       : 1
+  Termination status : LOCALLY_SOLVED
+  Message from the solver:
+  "Solve_Succeeded"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 2.50000e-01
+  Dual objective value : 7.50000e-01
+
+* Work counters
+  Solve time (sec)   : 1.50945e+00
+  Barrier iterations : 13
+

Indeed, the solution found is not globally optimal:

value(a), value(b)
(0.49999999667062867, 0.4999999966705758)

Note that the problem can be written equivalently as follows using registered functions. The difference is that the gradient and hessian will be computed via the Symbolic Differentiation provided by MultivariatePolynomials instead of JuMP's Automatic Differentiation:

f(a, b) = p(x => a, y => b)
+∇p = differentiate(p, [x, y])
+function ∇f(g, a, b)
+    for i in eachindex(g)
+        g[i] = ∇p[i](x => a, y => b)
+    end
+end
+∇²p = differentiate(∇p, [x, y])
+function ∇²f(H, a, b)
+    for j in axes(∇²p, 2)
+        for i in j:size(∇²p, 1)
+            H[i, j] = ∇²p[i, j](x => a, y => b)
+        end
+    end
+end
+using Ipopt
+gmodel = Model(Ipopt.Optimizer)
+@variable(gmodel, a >= 0)
+@variable(gmodel, b >= 0)
+@constraint(gmodel, a + b >= 1)
+register(gmodel, :f, 2, f, ∇f, ∇²f)
+@NLobjective(gmodel, Min, f(a, b))
+optimize!(gmodel)
This is Ipopt version 3.14.14, running with linear solver MUMPS 5.6.2.
+
+Number of nonzeros in equality constraint Jacobian...:        0
+Number of nonzeros in inequality constraint Jacobian.:        2
+Number of nonzeros in Lagrangian Hessian.............:        3
+
+Total number of variables............................:        2
+                     variables with only lower bounds:        2
+                variables with lower and upper bounds:        0
+                     variables with only upper bounds:        0
+Total number of equality constraints.................:        0
+Total number of inequality constraints...............:        1
+        inequality constraints with only lower bounds:        1
+   inequality constraints with lower and upper bounds:        0
+        inequality constraints with only upper bounds:        0
+
+iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
+   0  1.9999940e-06 9.80e-01 1.33e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
+   1  5.3716721e-05 9.40e-01 1.18e+00  -1.0 3.97e-01    -  3.23e-02 5.03e-02h  1
+   2  2.8887051e-01 0.00e+00 4.87e+01  -1.0 4.95e-01   2.0 1.00e+00 1.00e+00f  1
+   3  2.8997185e-01 0.00e+00 1.00e-06  -1.0 1.33e-03    -  1.00e+00 1.00e+00f  1
+   4  2.8022658e-01 0.00e+00 3.97e-01  -2.5 1.19e-02   1.5 1.00e+00 1.00e+00f  1
+   5  2.5585775e-01 0.00e+00 3.45e-01  -2.5 3.10e-02   1.0 1.00e+00 1.00e+00f  1
+   6  2.5292585e-01 0.00e+00 1.16e-01  -2.5 1.03e-02   0.6 1.00e+00 3.73e-01f  2
+   7  2.5283150e-01 0.00e+00 1.54e-04  -2.5 1.25e-04   0.1 1.00e+00 1.00e+00f  1
+   8  2.5021392e-01 0.00e+00 1.14e-02  -3.8 3.48e-03   0.5 1.00e+00 1.00e+00f  1
+   9  2.5014901e-01 0.00e+00 9.49e-05  -3.8 8.65e-05   0.0 1.00e+00 1.00e+00f  1
+iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
+  10  2.5000198e-01 0.00e+00 5.74e-04  -5.7 1.96e-04   0.5 1.00e+00 1.00e+00f  1
+  11  2.5000184e-01 0.00e+00 1.48e-06  -5.7 1.90e-07   0.9 1.00e+00 1.00e+00f  1
+  12  2.5000000e-01 0.00e+00 6.39e-06  -8.6 2.46e-06   0.4 1.00e+00 1.00e+00f  1
+  13  2.5000000e-01 0.00e+00 1.67e-10  -8.6 2.41e-11   0.8 1.00e+00 1.00e+00h  1
+
+Number of Iterations....: 13
+
+                                   (scaled)                 (unscaled)
+Objective...............:   2.4999999500590339e-01    2.4999999500590339e-01
+Dual infeasibility......:   1.6744750030994737e-10    1.6744750030994737e-10
+Constraint violation....:   0.0000000000000000e+00    0.0000000000000000e+00
+Variable bound violation:   0.0000000000000000e+00    0.0000000000000000e+00
+Complementarity.........:   2.5059035596801718e-09    2.5059035596801718e-09
+Overall NLP error.......:   2.5059035596801718e-09    2.5059035596801718e-09
+
+
+Number of objective function evaluations             = 19
+Number of objective gradient evaluations             = 14
+Number of equality constraint evaluations            = 0
+Number of inequality constraint evaluations          = 19
+Number of equality constraint Jacobian evaluations   = 0
+Number of inequality constraint Jacobian evaluations = 1
+Number of Lagrangian Hessian evaluations             = 13
+Total seconds in IPOPT                               = 0.046
+
+EXIT: Optimal Solution Found.

Even if we have the algebraic expressions of gradient and hessian, Ipopt is not using these symbolic expressions but only local information hence it can still only provide local guarantees:

solution_summary(gmodel)
* Solver : Ipopt
+
+* Status
+  Result count       : 1
+  Termination status : LOCALLY_SOLVED
+  Message from the solver:
+  "Solve_Succeeded"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 2.50000e-01
+  Dual objective value : 7.50000e-01
+
+* Work counters
+  Solve time (sec)   : 4.70459e-02
+  Barrier iterations : 13
+

and the same solution is found:

value(a), value(b)
(0.49999999667062867, 0.4999999966705758)

Sum-of-Squares approach

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import SCS
+scs = SCS.Optimizer
+import Dualization
+dual_scs = Dualization.dual_optimizer(scs)
#11 (generic function with 1 method)

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following program searches for the largest lower bound and finds zero.

model = SOSModel(dual_scs)
+@variable(model, α)
+@objective(model, Max, α)
+@constraint(model, c3, p >= α, domain = S)
+optimize!(model)
------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 10, constraints m: 25
+cones: 	  z: primal zero / dual free vars: 1
+	  s: psd vars: 24, ssize: 4
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 37, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 1.90e+01  1.01e+00  5.26e+01 -2.61e+01  1.00e-01  1.59e-04
+   125| 4.27e-05  3.97e-05  9.70e-06  8.12e-06  8.63e-01  1.16e-03
+------------------------------------------------------------------
+status:  solved
+timings: total: 1.16e-03s = setup: 8.04e-05s + solve: 1.08e-03s
+	 lin-sys: 7.47e-05s, cones: 8.77e-04s, accel: 7.22e-06s
+------------------------------------------------------------------
+objective = 0.000008
+------------------------------------------------------------------

This time, the termination status is OPTIMAL but this does not necessarily mean that we found the optimal solution to the polynomial optimization problem. This only means that CSDP founds an optimal solution to the Sum-of-Squares relaxation.

solution_summary(model)
* Solver : Dual model with SCS attached
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "solved"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 1.29679e-05
+  Dual objective value : 3.27176e-06
+
+* Work counters
+  Solve time (sec)   : 1.16082e-03
+

The feasibility of the primal solution guarantees that the objective value 0 is a lower bound to the polynomial optimization problem. The optimality means that it's the best lower bound we can get (at this degree of the hierarcy). Using the solution $(1/2, 1/2)$ found by Ipopt of objective value $1/4$ and this certificate of lower bound $0$ we know that the optimal objective value is in the interval $[0, 1/4]$ but we still do not know what it is (if we consider that we did not try the solutions $(1, 0)$ and $(0, 1)$ as done in the introduction). If the dual of the constraint c3 was atomic, its atoms would have given optimal solutions of objective value $0$ but that is not the case.

ν3 = moment_matrix(c3)
+atomic_measure(ν3, 1e-3) # Returns nothing as the dual is not atomic

Fortunately, there is a hierarchy of programs with increasingly better bounds that can be solved until we get one with atom dual variables. This comes from the way the Sum-of-Squares constraint with domain S is formulated. The polynomial $p - \alpha$ is guaranteed to be nonnegative over the domain S if there exists Sum-of-Squares polynomials $s_0$, $s_1$, $s_2$, $s_3$ such that

\[p - \alpha = s_0 + s_1 x + s_2 y + s_3 (x + y - 1).\]

Indeed, in the domain S, $x$, $y$ and $x + y - 1$ are nonnegative so the right-hand side is a sum of squares hence is nonnegative. Once the degrees of $s_1$, $s_2$ and $s_3$ have been decided, the degree needed for $s_0$ will be determined but we have a freedom in choosing the degrees of $s_1$, $s_2$ and $s_3$. By default, they are chosen so that the degrees of $s_1 x$, $s_2 y$ and $s_3 (x + y - 1)$ match those of $p - \alpha$ but this can be overwritten using the maxdegree keyword argument.

The maxdegree keyword argument

The maximum total degree (i.e. maximum sum of the exponents of $x$ and $y$) of the monomials of $p$ is 3 so the constraint in the program above is equivalent to @constraint(model, p >= α, domain = S, maxdegree = 3). That is, since $x$, $y$ and $x + y - 1$ have total degree 1, the sum of squares polynomials $s_1$, $s_2$ and $s_3$ have been chosen with maximum total degree $2$. Since these polynomials are sums of squares, their degree must be even so the next maximum total degree to try is 4. For this reason, the keywords maxdegree = 4 and maxdegree = 5 have the same effect in this example. In general, if the polynomials in the domain are not all odd or all even, each value of maxdegree has a different effect in the choice of the maximum total degree of some $s_i$.

model = SOSModel(dual_scs)
+@variable(model, α)
+@objective(model, Max, α)
+@constraint(model, c4, p >= α, domain = S, maxdegree = 4)
+optimize!(model)
------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 10, constraints m: 25
+cones: 	  z: primal zero / dual free vars: 1
+	  s: psd vars: 24, ssize: 4
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 37, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 1.90e+01  1.01e+00  5.26e+01 -2.61e+01  1.00e-01  1.86e-04
+   125| 4.27e-05  3.97e-05  9.70e-06  8.12e-06  8.63e-01  1.19e-03
+------------------------------------------------------------------
+status:  solved
+timings: total: 1.19e-03s = setup: 7.88e-05s + solve: 1.11e-03s
+	 lin-sys: 7.43e-05s, cones: 8.78e-04s, accel: 7.40e-06s
+------------------------------------------------------------------
+objective = 0.000008
+------------------------------------------------------------------

We can see that the basis of the moment matrix didn't increase:

moment_matrix(c4)
MomentMatrix with row/column basis:
+ MonomialBasis([1, y, x])
+And entries in a 3×3 SymMatrix{Float64}:
+ 0.9999988622359888  0.4999978058971253    0.499997805897121
+ 0.4999978058971253  0.49992054531120933   7.563537032711307e-5
+ 0.499997805897121   7.563537032711307e-5  0.49992054531120506

This is because of the Newton polytope reduction that determined that gram matrix will be zero for these degrees so it reduced the problem back to the equivalent of maxdegree 3 Let's turn this off with newton_polytope = nothing

function sos(solver, deg)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = S, maxdegree = deg, newton_polytope = nothing)
+    optimize!(model)
+    return model
+end
+dual_model4 = sos(dual_scs, 4)
------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 15, constraints m: 40
+cones: 	  z: primal zero / dual free vars: 1
+	  s: psd vars: 39, ssize: 4
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 52, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 1.06e+01  4.30e-01  3.19e+01 -1.57e+01  1.00e-01  1.91e-04
+   125| 2.44e-04  2.14e-05  1.20e-05 -4.90e-05  1.00e-01  1.71e-03
+------------------------------------------------------------------
+status:  solved
+timings: total: 1.71e-03s = setup: 8.06e-05s + solve: 1.63e-03s
+	 lin-sys: 1.09e-04s, cones: 1.33e-03s, accel: 3.28e-05s
+------------------------------------------------------------------
+objective = -0.000049
+------------------------------------------------------------------

We see that the lower bound is still 0:

solution_summary(dual_model4)
* Solver : Dual model with SCS attached
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "solved"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -4.29823e-05
+  Dual objective value : -5.49868e-05
+
+* Work counters
+  Solve time (sec)   : 1.71272e-03
+

Let's now look at which solution we can extract from the moment matrix:

dual_ν4 = moment_matrix(dual_model4[:c])
MomentMatrix with row/column basis:
+ MonomialBasis([1, y, x, y^2, x*y, x^2])
+And entries in a 6×6 SymMatrix{Float64}:
+  1.0000084649794703       0.5001118271563997      …   0.5003336181951755
+  0.5001118271563997       0.5003460975047918         -8.014565847567821e-5
+  0.500111827156376       -0.00012664913632054993      0.5004463755227944
+  0.5003336181952008       0.5004463755228222          1.952914136044233
+ -0.00012729223307204044  -9.194362986274147e-5       -1.8561449853462841
+  0.5003336181951755      -8.014565847567821e-5    …   8.524707147814647

Looking at the singular values, 4 seems to be a reasonable rank:

using LinearAlgebra
+svdvals(Matrix(dual_ν4.Q))
6-element Vector{Float64}:
+ 11.292137082084412
+  6.612780281630687
+  1.578866177150388
+  1.0597600660608397
+  0.45948547678078755
+  3.371754857737788e-16

The solution we extract is (0.5, 0.5) which is the solution found by Ipopt:

atomic_measure(dual_ν4, FixedRank(4))
Atomic measure on the variables x, y with 1 atoms:
+ at [0.5000778765242692, 0.5001018243812855] with weight 1.6079422332661

This process is quite sensitive numerically so let's try to solve it without dualization as well:

model4 = sos(scs, 4)
------------------------------------------------------------------
+	       SCS v3.2.4 - Splitting Conic Solver
+	(c) Brendan O'Donoghue, Stanford University, 2012
+------------------------------------------------------------------
+problem:  variables n: 40, constraints m: 54
+cones: 	  z: primal zero / dual free vars: 15
+	  s: psd vars: 39, ssize: 4
+settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
+	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
+	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
+	  acceleration_lookback: 10, acceleration_interval: 10
+	  compiled with openmp parallelization enabled
+lin-sys:  sparse-direct-amd-qdldl
+	  nnz(A): 91, nnz(P): 0
+------------------------------------------------------------------
+ iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
+------------------------------------------------------------------
+     0| 2.21e+01  1.35e+00  3.74e+01 -1.86e+01  1.00e-01  1.98e-04
+   175| 7.26e-05  8.28e-06  2.10e-05 -1.57e-05  1.00e-01  2.48e-03
+------------------------------------------------------------------
+status:  solved
+timings: total: 2.48e-03s = setup: 1.08e-04s + solve: 2.37e-03s
+	 lin-sys: 2.43e-04s, cones: 1.86e-03s, accel: 5.96e-05s
+------------------------------------------------------------------
+objective = -0.000016
+------------------------------------------------------------------

We see that the lower bound is again 0:

solution_summary(model4)
* Solver : SCS
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "solved"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 2.61826e-05
+  Dual objective value : 5.20758e-06
+
+* Work counters
+  Solve time (sec)   : 2.48243e-03
+

The moment matrix is the following

ν4 = moment_matrix(model4[:c])
MomentMatrix with row/column basis:
+ MonomialBasis([1, y, x, y^2, x*y, x^2])
+And entries in a 6×6 SymMatrix{Float64}:
+ 1.0000007181476624     0.49999933411667535   …  0.499983379029577
+ 0.49999933411667535    0.4999834837556788       8.47685915114403e-6
+ 0.4999993341166765     1.482541592461203e-5     0.49997241665096603
+ 0.4999833790295761     0.4999724166509653       0.26228006757487266
+ 1.5473299881402495e-5  7.379233003906931e-6     0.25448530696921917
+ 0.499983379029577      8.47685915114403e-6   …  0.796825700565282

Looking at the singular values, 3 seems to be a reasonable rank:

svdvals(Matrix(ν4.Q))
6-element Vector{Float64}:
+ 2.1989525826317653
+ 1.0175199095063976
+ 0.6030514893217399
+ 0.019380459836853832
+ 0.016994381823767828
+ 5.714524905397067e-16

This time, the dual variable is atomic as it is the moments of the measure $0.5 \delta(x-1, y) + 0.5 \delta(x, y-1)$ where $\delta(x, y)$ is the dirac measure centered at $(0, 0)$. Therefore the program provides both a certificate that $0$ is a lower bound and a certificate that it is also an upper bound since it is attained at the global minimizers $(1, 0)$ and $(0, 1)$.

atomic_measure(ν4, FixedRank(3))
Atomic measure on the variables x, y with 2 atoms:
+ at [0.9946508364409374, 0.005346125382867863] with weight 0.5511753483416816
+ at [-0.011834484693471814, 1.0118314465172769] with weight 0.528574707003423

A deeper look into atom extraction

The moment matrix is transformed into a system of polynomials equations whose solutions give the atoms. This transformation uses the SVD decomposition of the moment matrix and discards the equations corresponding to the lowest singular values. When this system of equation has an infinite number of solutions, atomic_measure concludes that the measure is not atomic. For instance, with maxdegree = 3, we obtain the system $x + y = 1$ which contains a whole line of solution. This explains atomic_measure returned nothing.

ν3 = moment_matrix(c3)
+SumOfSquares.MultivariateMoments.compute_support!(ν3, LeadingRelativeRankTol(1e-3))

With maxdegree = 4, we obtain the system

\[\begin{aligned} + x + y & = 1\\ + y^2 & = y\\ + xy & = 0\\ + -y + y^2 - x*y & = 0 + y^2 - 2y + 1 & = x^2 +\end{aligned}\]

ν4 = moment_matrix(model4[:c])
+SumOfSquares.MultivariateMoments.compute_support!(ν4, FixedRank(3))

This system can be reduced to the equivalent system

\[\begin{aligned} + x + y & = 1\\ + y^2 & = y +\end{aligned}\]

which has the solutions $(0, 1)$ and $(1, 0)$.

SemialgebraicSets.compute_gröbner_basis!(ideal(ν4.support))
+ν4.support
Algebraic Set defined by 2 equalities
+ -0.9999969618238052 + 1.0000000000000002*y + x = 0
+ 0.005409377779409965 - 1.0171775719001446*y + y^2 = 0
+

The solutions of this system then give the minimizers

collect(ν4.support)
2-element Vector{Vector{Float64}}:
+ [0.9946508364409373, 0.005346125382867784]
+ [-0.01183448469347187, 1.0118314465172766]

The function atomic_measure then reuses the matrix of moments to find the weights $1/2$, $1/2$ corresponding to the diracs centered respectively at $(0, 1)$ and $(1, 0)$. This details how the function obtained the result $0.5 \delta(x-1, y) + 0.5 \delta(x, y-1)$ given in the previous section.

HomotopyContinuation

As discussed in the previous section, the atom extraction relies on the solution of a system of algebraic equations. The atomic_measure function takes an optional algebraic_solver argument that is used to solve this system of equation. If no solver is provided, the default solver of SemialgebraicSets.jl is used which currently computes the Gröbner basis, then the multiplication matrices and then the Schur decomposition of a random combination of these matrices. As the system of equations is obtained from a numerical solution and is represented using floating point coefficients, homotopy continuation is recommended as it is more numerically robust than Gröbner basis computation. The following uses homotopy continuation to solve the system of equations.

using HomotopyContinuation
+algebraic_solver = SemialgebraicSetsHCSolver(; excess_residual_tol = 1e-1, real_tol = 1e-1, compile = false)
+atomic_measure(ν4, FixedRank(3), Echelon(), algebraic_solver)
Atomic measure on the variables x, y with 2 atoms:
+ at [-0.001001824129714714, 0.9835798899337953] with weight 0.5610250566565054
+ at [1.012160441245297, -0.0010152020873548243] with weight 0.5276857744320876

As the system has 3 equations for 2 variables and the coefficients of the equations are to be treated with tolerance since they originate from the solution of an SDP, we need to set excess_residual_tol and real_tol to a high tolerance otherwise, HomotopyContinuation would consider that there is no solution. Indeed, as the system is overdetermined (it has more equations than variables) HomotopyContinuation expects to have excess solution hence it filters out excess solution among the solution found. It determines which solution are in excess by comparing the infinity norm of the residuals of the equations at the solution with excess_residual_tol. It also filters out solution for which the absolute value of the imaginary part of one of the entry is larger than real_tol and strips out the imaginary part. The raw solutions obtained by HomotopyContinuation can be obtained as follows:

F = HomotopyContinuation.System(ν4.support)
+res = HomotopyContinuation.solve(F, algebraic_solver.options...)
+path_results(res)
4-element Vector{HomotopyContinuation.PathResult}:
+ PathResult:
+ • return_code → :excess_solution
+ • solution → ComplexF64[-0.6982352242178278 - 2.182590945806583im, 1.0671338157327181 - 0.7008178358294207im]
+ • accuracy → 4.8605
+ • residual → 1.2658
+ • condition_jacobian → 3.0677
+ • steps → 32 / 0
+ • extended_precision → false
+ • path_number → 1
+
+ PathResult:
+ • return_code → :excess_solution
+ • solution → ComplexF64[36.68902156504333 + 8.05324243346915im, 38.47718678316344 + 9.518728897463637im]
+ • accuracy → 125.51
+ • residual → 24.772
+ • condition_jacobian → 130.69
+ • steps → 44 / 0
+ • extended_precision → false
+ • path_number → 2
+
+ PathResult:
+ • return_code → :excess_solution
+ • solution → ComplexF64[-0.013730969630867364 + 0.016849839727248794im, 1.0040936356362897 + 0.00234221696592751im]
+ • accuracy → 0.035362
+ • residual → 0.016455
+ • condition_jacobian → 19.386
+ • steps → 31 / 0
+ • extended_precision → false
+ • path_number → 3
+
+ PathResult:
+ • return_code → :excess_solution
+ • solution → ComplexF64[1.0034512309336605 - 0.0012159509999119986im, 0.006418797954327637 - 0.003954284064334483im]
+ • accuracy → 0.018352
+ • residual → 0.0052206
+ • condition_jacobian → 24.096
+ • steps → 31 / 0
+ • extended_precision → false
+ • path_number → 4
+

The printed residual above shows why 1e-1 allows to filter how the 2 actual solutions from the 2 excess solutions.


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/qcqp.ipynb b/previews/PR347/generated/Polynomial Optimization/qcqp.ipynb new file mode 100644 index 000000000..dd689afe5 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/qcqp.ipynb @@ -0,0 +1,336 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Nonconvex quadratically constrained quadratic programs" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: [Hesse1973](@cite), [Floudas1999; Section 3.4](@cite), [Laurent2008; Example 6.22](@cite) and [Lasserre2009; Table 5.1](@cite)" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We consider the nonconvex Quadratically Constrained Quadratic Programs (QCQP)\n", + "introduced in [H73].\n", + "Consider now the polynomial optimization problem [Laurent2008; Example 6.22](@cite) of\n", + "maximizing the convex quadratic function\n", + "(hence nonconvex since convex programs should either maximize concave functions\n", + "or minimize convex functions)\n", + "$25(x_1 - 2)^2 + (x_2 - 2)^2 + (x_3 - 1)^2 + (x_4 - 4)^2 + (x_5 - 1)^2 + (x_6 - 4)^2$\n", + "over the basic semialgebraic set defined by the nonconvex quadratic inequalities\n", + "$(x_3 - 3)^2 + x_4 \\ge 4$,\n", + "$(x_5 - 3)^2 + x_6 \\ge 4$,\n", + "and linear inequalities\n", + "$x_1 - 3x_2 \\le 2$,\n", + "$-x_1 + x_2 \\le 2$,\n", + "$2 \\le x_1 + x_2 \\le 6$,\n", + "$0 \\le x_1, x_2$,\n", + "$1 \\le x_3 \\le 5$,\n", + "$0 \\le x_4 \\le 6$,\n", + "$1 \\le x_5 \\le 5$,\n", + "$0 \\le x_6 \\le 10$,\n", + "$x_2 \\le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36$ and the box constraints\n", + "$0 \\le x_1 \\le 3$ and $0 \\le x_2 \\le 4$," + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Basic semialgebraic Set defined by no equality\n16 inequalities\n x[1] ≥ 0\n x[2] ≥ 0\n -1 + x[3] ≥ 0\n 5 - x[3] ≥ 0\n x[4] ≥ 0\n 6 - x[4] ≥ 0\n -1 + x[5] ≥ 0\n 5 - x[5] ≥ 0\n x[6] ≥ 0\n 10 - x[6] ≥ 0\n 5 + x[4] - 6*x[3] + x[3]^2 ≥ 0\n 5 + x[6] - 6*x[5] + x[5]^2 ≥ 0\n 2 + 3*x[2] - x[1] ≥ 0\n 2 - x[2] + x[1] ≥ 0\n 6 - x[2] - x[1] ≥ 0\n -2 + x[2] + x[1] ≥ 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:6]\n", + "centers = [2, 2, 1, 4, 1, 4]\n", + "weights = [25, 1, 1, 1, 1, 1]\n", + "p = -weights' * (x .- centers).^2\n", + "using SumOfSquares\n", + "K = @set x[1] >= 0 && x[2] >= 0 &&\n", + " x[3] >= 1 && x[3] <= 5 &&\n", + " x[4] >= 0 && x[4] <= 6 &&\n", + " x[5] >= 1 && x[5] <= 5 &&\n", + " x[6] >= 0 && x[6] <= 10 &&\n", + " (x[3] - 3)^2 + x[4] >= 4 &&\n", + " (x[5] - 3)^2 + x[6] >= 4 &&\n", + " x[1] - 3x[2] <= 2 &&\n", + " -x[1] + x[2] <= 2 &&\n", + " x[1] + x[2] <= 6 &&\n", + " x[1] + x[2] >= 2" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Clarabel.MOIwrapper.Optimizer" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import Clarabel\n", + "solver = Clarabel.Optimizer" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "solve (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "function solve(d)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = K, maxdegree = d)\n", + " optimize!(model)\n", + " println(solution_summary(model))\n", + " return model\n", + "end" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The first level of the hierarchy cannot find any lower bound." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 45\n", + " constraints = 72\n", + " nnz(P) = 0\n", + " nnz(A) = 109\n", + " cones (total) = 3\n", + " : Zero = 1, numel = 28\n", + " : Nonnegative = 1, numel = 16\n", + " : PSDTriangle = 1, numel = 28\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 7.6836e+01 7.6836e+01 3.70e-16 4.13e-01 1.83e-01 1.00e+00 1.04e+02 ------ \n", + " 1 2.3712e+04 2.9567e+04 2.47e-01 3.63e-01 7.20e-02 5.92e+03 6.57e+01 9.27e-01 \n", + " 2 -2.2453e+02 9.6600e+02 5.30e+00 2.92e-01 6.59e-02 1.19e+03 5.27e+01 5.22e-01 \n", + " 3 1.9334e+03 7.3247e+03 2.79e+00 1.09e-01 1.40e-02 5.39e+03 1.13e+01 8.20e-01 \n", + " 4 1.7396e+04 3.1882e+04 8.33e-01 1.60e-02 1.87e-03 1.45e+04 2.37e+00 9.55e-01 \n", + " 5 1.2768e+05 2.1916e+05 7.16e-01 2.23e-03 2.46e-04 9.15e+04 3.33e-01 8.92e-01 \n", + " 6 5.0101e+06 8.4176e+06 6.80e-01 5.35e-05 5.80e-06 3.41e+06 8.11e-03 9.88e-01 \n", + " 7 4.3548e+08 7.3167e+08 6.80e-01 6.23e-07 6.75e-08 2.96e+08 9.44e-05 9.88e-01 \n", + " 8 2.2618e+10 3.8076e+10 6.83e-01 1.25e-08 1.35e-09 1.55e+10 1.88e-06 9.80e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = primal infeasible\n", + "solve time = 283ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : INFEASIBLE\n", + " Message from the solver:\n", + " \"PRIMAL_INFEASIBLE\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : INFEASIBLE_POINT\n", + " Dual status : INFEASIBILITY_CERTIFICATE\n", + " Objective value : -2.26177e+10\n", + " Dual objective value : -3.80764e+10\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 2.83361e-01\n", + " Barrier iterations : 8\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model2 = solve(2)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "The second level of the hierarchy finds the lower bound of `-310`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 423\n", + " constraints = 506\n", + " nnz(P) = 0\n", + " nnz(A) = 1243\n", + " cones (total) = 17\n", + " : Zero = 1, numel = 84\n", + " : Nonnegative = 1, numel = 2\n", + " : PSDTriangle = 15, numel = (28,28,28,28,...,28)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 1.3550e+02 1.3550e+02 2.10e-16 1.88e-01 7.50e-01 1.00e+00 1.28e+01 ------ \n", + " 1 1.3966e+02 1.4303e+02 2.41e-02 8.99e-02 2.53e-01 3.94e+00 4.70e+00 7.91e-01 \n", + " 2 1.6240e+02 1.7566e+02 8.17e-02 4.83e-02 5.65e-02 1.38e+01 1.71e+00 8.78e-01 \n", + " 3 1.5720e+02 1.6295e+02 3.65e-02 2.05e-02 2.04e-02 5.95e+00 6.72e-01 6.85e-01 \n", + " 4 1.4675e+02 1.5215e+02 3.68e-02 1.38e-02 1.22e-02 5.53e+00 4.15e-01 6.37e-01 \n", + " 5 1.8037e+02 1.8247e+02 1.17e-02 3.91e-03 2.81e-03 2.14e+00 9.73e-02 7.90e-01 \n", + " 6 2.1477e+02 2.1622e+02 6.73e-03 2.42e-03 1.58e-03 1.47e+00 5.73e-02 5.20e-01 \n", + " 7 2.5401e+02 2.5440e+02 1.55e-03 5.37e-04 2.93e-04 3.99e-01 1.15e-02 8.97e-01 \n", + " 8 2.7007e+02 2.7034e+02 9.95e-04 2.02e-04 8.19e-05 2.71e-01 3.47e-03 8.17e-01 \n", + " 9 2.8259e+02 2.8277e+02 6.14e-04 9.25e-05 2.93e-05 1.75e-01 1.31e-03 8.24e-01 \n", + " 10 2.8775e+02 2.8799e+02 8.37e-04 8.09e-05 1.51e-05 2.42e-01 8.16e-04 6.61e-01 \n", + " 11 3.0102e+02 3.0109e+02 2.34e-04 2.58e-05 4.43e-06 7.09e-02 2.48e-04 9.90e-01 \n", + " 12 3.0953e+02 3.0953e+02 1.29e-05 1.36e-06 2.05e-07 4.01e-03 1.22e-05 9.54e-01 \n", + " 13 3.0999e+02 3.0999e+02 2.13e-07 2.27e-08 3.40e-09 6.64e-05 2.02e-07 9.83e-01 \n", + " 14 3.1000e+02 3.1000e+02 5.77e-09 6.12e-10 9.18e-11 1.80e-06 5.46e-09 9.73e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 45.3ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -3.10000e+02\n", + " Dual objective value : -3.10000e+02\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 4.52965e-02\n", + " Barrier iterations : 14\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model3 = solve(4)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/qcqp.jl b/previews/PR347/generated/Polynomial Optimization/qcqp.jl new file mode 100644 index 000000000..46517ece0 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/qcqp.jl @@ -0,0 +1,38 @@ +using DynamicPolynomials +@polyvar x[1:6] +centers = [2, 2, 1, 4, 1, 4] +weights = [25, 1, 1, 1, 1, 1] +p = -weights' * (x .- centers).^2 +using SumOfSquares +K = @set x[1] >= 0 && x[2] >= 0 && + x[3] >= 1 && x[3] <= 5 && + x[4] >= 0 && x[4] <= 6 && + x[5] >= 1 && x[5] <= 5 && + x[6] >= 0 && x[6] <= 10 && + (x[3] - 3)^2 + x[4] >= 4 && + (x[5] - 3)^2 + x[6] >= 4 && + x[1] - 3x[2] <= 2 && + -x[1] + x[2] <= 2 && + x[1] + x[2] <= 6 && + x[1] + x[2] >= 2 + +import Clarabel +solver = Clarabel.Optimizer + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +model2 = solve(2) +nothing # hide + +model3 = solve(4) +nothing # hide + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/qcqp/index.html b/previews/PR347/generated/Polynomial Optimization/qcqp/index.html new file mode 100644 index 000000000..a07582877 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/qcqp/index.html @@ -0,0 +1,165 @@ + +Nonconvex quadratically constrained quadratic programs · SumOfSquares

Nonconvex quadratically constrained quadratic programs

Adapted from: (Hesse, 1973), (Floudas et al., 1999; Section 3.4), (Laurent, 2008; Example 6.22) and (Lasserre, 2009; Table 5.1)

We consider the nonconvex Quadratically Constrained Quadratic Programs (QCQP) introduced in [H73]. Consider now the polynomial optimization problem (Laurent, 2008; Example 6.22) of maximizing the convex quadratic function (hence nonconvex since convex programs should either maximize concave functions or minimize convex functions) $25(x_1 - 2)^2 + (x_2 - 2)^2 + (x_3 - 1)^2 + (x_4 - 4)^2 + (x_5 - 1)^2 + (x_6 - 4)^2$ over the basic semialgebraic set defined by the nonconvex quadratic inequalities $(x_3 - 3)^2 + x_4 \ge 4$, $(x_5 - 3)^2 + x_6 \ge 4$, and linear inequalities $x_1 - 3x_2 \le 2$, $-x_1 + x_2 \le 2$, $2 \le x_1 + x_2 \le 6$, $0 \le x_1, x_2$, $1 \le x_3 \le 5$, $0 \le x_4 \le 6$, $1 \le x_5 \le 5$, $0 \le x_6 \le 10$, $x_2 \le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36$ and the box constraints $0 \le x_1 \le 3$ and $0 \le x_2 \le 4$,

using DynamicPolynomials
+@polyvar x[1:6]
+centers = [2, 2, 1, 4, 1, 4]
+weights = [25, 1, 1, 1, 1, 1]
+p = -weights' * (x .- centers).^2
+using SumOfSquares
+K = @set x[1] >= 0 && x[2] >= 0 &&
+    x[3] >= 1 && x[3] <= 5 &&
+    x[4] >= 0 && x[4] <= 6 &&
+    x[5] >= 1 && x[5] <= 5 &&
+    x[6] >= 0 && x[6] <= 10 &&
+    (x[3] - 3)^2 + x[4] >= 4 &&
+    (x[5] - 3)^2 + x[6] >= 4 &&
+    x[1] - 3x[2] <= 2 &&
+    -x[1] + x[2] <= 2 &&
+    x[1] + x[2] <= 6 &&
+    x[1] + x[2] >= 2
Basic semialgebraic Set defined by no equality
+16 inequalities
+ x[1] ≥ 0
+ x[2] ≥ 0
+ -1 + x[3] ≥ 0
+ 5 - x[3] ≥ 0
+ x[4] ≥ 0
+ 6 - x[4] ≥ 0
+ -1 + x[5] ≥ 0
+ 5 - x[5] ≥ 0
+ x[6] ≥ 0
+ 10 - x[6] ≥ 0
+ 5 + x[4] - 6*x[3] + x[3]^2 ≥ 0
+ 5 + x[6] - 6*x[5] + x[5]^2 ≥ 0
+ 2 + 3*x[2] - x[1] ≥ 0
+ 2 - x[2] + x[1] ≥ 0
+ 6 - x[2] - x[1] ≥ 0
+ -2 + x[2] + x[1] ≥ 0
+

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import Clarabel
+solver = Clarabel.Optimizer
Clarabel.MOIwrapper.Optimizer

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.

function solve(d)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = K, maxdegree = d)
+    optimize!(model)
+    println(solution_summary(model))
+    return model
+end
solve (generic function with 1 method)

The first level of the hierarchy cannot find any lower bound.

model2 = solve(2)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 45
+  constraints   = 72
+  nnz(P)        = 0
+  nnz(A)        = 109
+  cones (total) = 3
+    : Zero        = 1,  numel = 28
+    : Nonnegative = 1,  numel = 16
+    : PSDTriangle = 1,  numel = 28
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   7.6836e+01   7.6836e+01  3.70e-16  4.13e-01  1.83e-01  1.00e+00  1.04e+02   ------
+  1   2.3712e+04   2.9567e+04  2.47e-01  3.63e-01  7.20e-02  5.92e+03  6.57e+01  9.27e-01
+  2  -2.2453e+02   9.6600e+02  5.30e+00  2.92e-01  6.59e-02  1.19e+03  5.27e+01  5.22e-01
+  3   1.9334e+03   7.3247e+03  2.79e+00  1.09e-01  1.40e-02  5.39e+03  1.13e+01  8.20e-01
+  4   1.7396e+04   3.1882e+04  8.33e-01  1.60e-02  1.87e-03  1.45e+04  2.37e+00  9.55e-01
+  5   1.2768e+05   2.1916e+05  7.16e-01  2.23e-03  2.46e-04  9.15e+04  3.33e-01  8.92e-01
+  6   5.0101e+06   8.4176e+06  6.80e-01  5.35e-05  5.80e-06  3.41e+06  8.11e-03  9.88e-01
+  7   4.3548e+08   7.3167e+08  6.80e-01  6.23e-07  6.75e-08  2.96e+08  9.44e-05  9.88e-01
+  8   2.2618e+10   3.8076e+10  6.83e-01  1.25e-08  1.35e-09  1.55e+10  1.88e-06  9.80e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = primal infeasible
+solve time = 2.40ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : INFEASIBLE
+  Message from the solver:
+  "PRIMAL_INFEASIBLE"
+
+* Candidate solution (result #1)
+  Primal status      : INFEASIBLE_POINT
+  Dual status        : INFEASIBILITY_CERTIFICATE
+  Objective value    : -2.26177e+10
+  Dual objective value : -3.80764e+10
+
+* Work counters
+  Solve time (sec)   : 2.40036e-03
+  Barrier iterations : 8

The second level of the hierarchy finds the lower bound of -310.

model3 = solve(4)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 423
+  constraints   = 506
+  nnz(P)        = 0
+  nnz(A)        = 1243
+  cones (total) = 17
+    : Zero        = 1,  numel = 84
+    : Nonnegative = 1,  numel = 2
+    : PSDTriangle = 15,  numel = (28,28,28,28,...,28)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0   1.3550e+02   1.3550e+02  2.10e-16  1.88e-01  7.50e-01  1.00e+00  1.28e+01   ------
+  1   1.3966e+02   1.4303e+02  2.41e-02  8.99e-02  2.53e-01  3.94e+00  4.70e+00  7.91e-01
+  2   1.6240e+02   1.7566e+02  8.17e-02  4.83e-02  5.65e-02  1.38e+01  1.71e+00  8.78e-01
+  3   1.5720e+02   1.6295e+02  3.65e-02  2.05e-02  2.04e-02  5.95e+00  6.72e-01  6.85e-01
+  4   1.4675e+02   1.5215e+02  3.68e-02  1.38e-02  1.22e-02  5.53e+00  4.15e-01  6.37e-01
+  5   1.8037e+02   1.8247e+02  1.17e-02  3.91e-03  2.81e-03  2.14e+00  9.73e-02  7.90e-01
+  6   2.1477e+02   2.1622e+02  6.73e-03  2.42e-03  1.58e-03  1.47e+00  5.73e-02  5.20e-01
+  7   2.5401e+02   2.5440e+02  1.55e-03  5.37e-04  2.93e-04  3.99e-01  1.15e-02  8.97e-01
+  8   2.7007e+02   2.7034e+02  9.95e-04  2.02e-04  8.19e-05  2.71e-01  3.47e-03  8.17e-01
+  9   2.8259e+02   2.8277e+02  6.14e-04  9.25e-05  2.93e-05  1.75e-01  1.31e-03  8.24e-01
+ 10   2.8775e+02   2.8799e+02  8.37e-04  8.09e-05  1.51e-05  2.42e-01  8.16e-04  6.61e-01
+ 11   3.0102e+02   3.0109e+02  2.34e-04  2.58e-05  4.43e-06  7.09e-02  2.48e-04  9.90e-01
+ 12   3.0953e+02   3.0953e+02  1.29e-05  1.36e-06  2.05e-07  4.01e-03  1.22e-05  9.54e-01
+ 13   3.0999e+02   3.0999e+02  2.13e-07  2.27e-08  3.40e-09  6.64e-05  2.02e-07  9.83e-01
+ 14   3.1000e+02   3.1000e+02  5.77e-09  6.12e-10  9.18e-11  1.80e-06  5.46e-09  9.73e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 42.4ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -3.10000e+02
+  Dual objective value : -3.10000e+02
+
+* Work counters
+  Solve time (sec)   : 4.23797e-02
+  Barrier iterations : 14

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Polynomial Optimization/qp.ipynb b/previews/PR347/generated/Polynomial Optimization/qp.ipynb new file mode 100644 index 000000000..fbcc213ad --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/qp.ipynb @@ -0,0 +1,322 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Nonconvex QP" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: of [Floudas1999; Section 2.2](@cite), [Lasserre2009; Table 5.1](@cite)" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Introduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Consider the nonconvex Quadratic Program (QP) from [Floudas1999; Section 2.2](@cite)\n", + "that minimizes the *concave* function $c^\\top x - x^\\top Qx / 2$\n", + "over the polyhedron obtained by intersecting the hypercube $[0, 1]^5$\n", + "with the halfspace $10x_1 + 12x_2 + 11x_3 + 7x_4 + 4x_5 \\le 40$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Basic semialgebraic Set defined by no equality\n11 inequalities\n x[1] ≥ 0\n 1 - x[1] ≥ 0\n x[2] ≥ 0\n 1 - x[2] ≥ 0\n x[3] ≥ 0\n 1 - x[3] ≥ 0\n x[4] ≥ 0\n 1 - x[4] ≥ 0\n x[5] ≥ 0\n 1 - x[5] ≥ 0\n 40 - 4*x[5] - 7*x[4] - 11*x[3] - 12*x[2] - 10*x[1] ≥ 0\n" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra\n", + "c = [42, 44, 45, 47, 47.5]\n", + "Q = 100I\n", + "\n", + "using DynamicPolynomials\n", + "@polyvar x[1:5]\n", + "p = c'x - x' * Q * x / 2\n", + "using SumOfSquares\n", + "K = @set x[1] >= 0 && x[1] <= 1 &&\n", + " x[2] >= 0 && x[2] <= 1 &&\n", + " x[3] >= 0 && x[3] <= 1 &&\n", + " x[4] >= 0 && x[4] <= 1 &&\n", + " x[5] >= 0 && x[5] <= 1 &&\n", + " 10x[1] + 12x[2] + 11x[3] + 7x[4] + 4x[5] <= 40" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We will now see how to find the optimal solution using Sum of Squares Programming.\n", + "We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Clarabel.MOIwrapper.Optimizer" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import Clarabel\n", + "solver = Clarabel.Optimizer" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "A Sum-of-Squares certificate that $p \\ge \\alpha$ over the domain `S`, ensures that $\\alpha$ is a lower bound to the polynomial optimization problem.\n", + "The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "solve (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "function solve(d)\n", + " model = SOSModel(solver)\n", + " @variable(model, α)\n", + " @objective(model, Max, α)\n", + " @constraint(model, c, p >= α, domain = K, maxdegree = d)\n", + " optimize!(model)\n", + " println(solution_summary(model))\n", + " return model\n", + "end" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "The first level of the hierarchy does not give any lower bound:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 33\n", + " constraints = 53\n", + " nnz(P) = 0\n", + " nnz(A) = 75\n", + " cones (total) = 3\n", + " : Zero = 1, numel = 21\n", + " : Nonnegative = 1, numel = 11\n", + " : PSDTriangle = 1, numel = 21\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 -1.5207e+02 -1.5207e+02 0.00e+00 5.27e-01 7.37e-02 1.00e+00 9.59e+01 ------ \n", + " 1 2.4388e+04 2.5071e+04 2.80e-02 7.15e-02 1.04e-02 6.91e+02 1.14e+01 9.66e-01 \n", + " 2 1.6512e+05 1.7080e+05 3.44e-02 3.79e-03 5.18e-04 5.68e+03 6.86e-01 9.47e-01 \n", + " 3 1.6216e+07 1.7985e+07 1.09e-01 7.36e-04 1.00e-04 1.77e+06 1.34e-01 8.78e-01 \n", + " 4 1.6199e+09 1.8067e+09 1.15e-01 1.41e-05 1.91e-06 1.87e+08 2.55e-03 9.81e-01 \n", + " 5 1.8390e+10 2.0786e+10 1.30e-01 2.05e-07 2.78e-08 2.40e+09 3.71e-05 9.86e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = primal infeasible\n", + "solve time = 1.59ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : INFEASIBLE\n", + " Message from the solver:\n", + " \"PRIMAL_INFEASIBLE\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : INFEASIBLE_POINT\n", + " Dual status : INFEASIBILITY_CERTIFICATE\n", + " Objective value : -1.83898e+10\n", + " Dual objective value : -2.07856e+10\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 1.58706e-03\n", + " Barrier iterations : 5\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model2 = solve(2)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Indeed, as the constraints have degree 1 and their multipliers are SOS\n", + "so they have an even degree, with `maxdegree` 2 we can only use degree 0\n", + "multipliers hence constants. The terms of maximal degree in resulting\n", + "sum will therefore only be in `-x' * Q * x/2` hence it is not SOS whatever\n", + "is the value of the multipliers. Let's try with `maxdegree` 3 so that the\n", + "multipliers can be quadratic.\n", + "This second level is now feasible and gives a lower bound of `-22`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------------------------------\n", + " Clarabel.jl v0.7.1 - Clever Acronym \n", + " (c) Paul Goulart \n", + " University of Oxford, 2022 \n", + "-------------------------------------------------------------\n", + "\n", + "problem:\n", + " variables = 253\n", + " constraints = 308\n", + " nnz(P) = 0\n", + " nnz(A) = 715\n", + " cones (total) = 13\n", + " : Zero = 1, numel = 56\n", + " : PSDTriangle = 12, numel = (21,21,21,21,...,21)\n", + "\n", + "settings:\n", + " linear algebra: direct / qdldl, precision: Float64\n", + " max iter = 200, time limit = Inf, max step = 0.990\n", + " tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,\n", + " static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32\n", + " dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07\n", + " iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12, \n", + " max iter = 10, stop ratio = 5.0\n", + " equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05\n", + " max iter = 10\n", + "\n", + "iter pcost dcost gap pres dres k/t μ step \n", + "---------------------------------------------------------------------------------------------\n", + " 0 -1.3991e+01 -1.3991e+01 6.35e-16 3.32e-01 9.13e-02 1.00e+00 9.46e+00 ------ \n", + " 1 2.4255e+02 2.4996e+02 3.06e-02 1.45e-01 3.32e-02 8.38e+00 2.67e+00 9.00e-01 \n", + " 2 7.3705e+01 7.9821e+01 8.30e-02 5.20e-02 1.50e-02 6.48e+00 1.52e+00 6.49e-01 \n", + " 3 3.6450e+01 3.8243e+01 4.92e-02 1.15e-02 3.41e-03 1.86e+00 4.41e-01 7.97e-01 \n", + " 4 3.1397e+01 3.2740e+01 4.28e-02 6.37e-03 1.91e-03 1.39e+00 2.70e-01 6.34e-01 \n", + " 5 2.1768e+01 2.2034e+01 1.22e-02 1.23e-03 3.40e-04 2.75e-01 5.65e-02 8.06e-01 \n", + " 6 2.2259e+01 2.2326e+01 2.99e-03 4.09e-04 1.03e-04 6.95e-02 1.91e-02 8.17e-01 \n", + " 7 2.1905e+01 2.1925e+01 9.14e-04 1.28e-04 3.24e-05 2.10e-02 6.08e-03 7.38e-01 \n", + " 8 2.1973e+01 2.1978e+01 1.91e-04 4.09e-05 1.02e-05 4.52e-03 1.97e-03 9.90e-01 \n", + " 9 2.2000e+01 2.2000e+01 2.57e-06 5.82e-07 1.41e-07 6.11e-05 2.82e-05 9.90e-01 \n", + " 10 2.2000e+01 2.2000e+01 2.82e-08 6.39e-09 1.55e-09 6.70e-07 3.09e-07 9.89e-01 \n", + " 11 2.2000e+01 2.2000e+01 3.49e-10 7.90e-11 1.92e-11 8.30e-09 3.83e-09 9.88e-01 \n", + "---------------------------------------------------------------------------------------------\n", + "Terminated with status = solved\n", + "solve time = 13.2ms\n", + "* Solver : Clarabel\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"SOLVED\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : -2.20000e+01\n", + " Dual objective value : -2.20000e+01\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 1.32061e-02\n", + " Barrier iterations : 11\n", + "\n" + ] + } + ], + "cell_type": "code", + "source": [ + "model3 = solve(3)\n", + "nothing # hide" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Polynomial Optimization/qp.jl b/previews/PR347/generated/Polynomial Optimization/qp.jl new file mode 100644 index 000000000..baa9b362d --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/qp.jl @@ -0,0 +1,35 @@ +using LinearAlgebra +c = [42, 44, 45, 47, 47.5] +Q = 100I + +using DynamicPolynomials +@polyvar x[1:5] +p = c'x - x' * Q * x / 2 +using SumOfSquares +K = @set x[1] >= 0 && x[1] <= 1 && + x[2] >= 0 && x[2] <= 1 && + x[3] >= 0 && x[3] <= 1 && + x[4] >= 0 && x[4] <= 1 && + x[5] >= 0 && x[5] <= 1 && + 10x[1] + 12x[2] + 11x[3] + 7x[4] + 4x[5] <= 40 + +import Clarabel +solver = Clarabel.Optimizer + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +model2 = solve(2) +nothing # hide + +model3 = solve(3) +nothing # hide + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Polynomial Optimization/qp/index.html b/previews/PR347/generated/Polynomial Optimization/qp/index.html new file mode 100644 index 000000000..a3b0c29f5 --- /dev/null +++ b/previews/PR347/generated/Polynomial Optimization/qp/index.html @@ -0,0 +1,150 @@ + +Nonconvex QP · SumOfSquares

Nonconvex QP

Adapted from: of (Floudas et al., 1999; Section 2.2), (Lasserre, 2009; Table 5.1)

Introduction

Consider the nonconvex Quadratic Program (QP) from (Floudas et al., 1999; Section 2.2) that minimizes the concave function $c^\top x - x^\top Qx / 2$ over the polyhedron obtained by intersecting the hypercube $[0, 1]^5$ with the halfspace $10x_1 + 12x_2 + 11x_3 + 7x_4 + 4x_5 \le 40$.

using LinearAlgebra
+c = [42, 44, 45, 47, 47.5]
+Q = 100I
+
+using DynamicPolynomials
+@polyvar x[1:5]
+p = c'x - x' * Q * x / 2
+using SumOfSquares
+K = @set x[1] >= 0 && x[1] <= 1 &&
+         x[2] >= 0 && x[2] <= 1 &&
+         x[3] >= 0 && x[3] <= 1 &&
+         x[4] >= 0 && x[4] <= 1 &&
+         x[5] >= 0 && x[5] <= 1 &&
+         10x[1] + 12x[2] + 11x[3] + 7x[4] + 4x[5] <= 40
Basic semialgebraic Set defined by no equality
+11 inequalities
+ x[1] ≥ 0
+ 1 - x[1] ≥ 0
+ x[2] ≥ 0
+ 1 - x[2] ≥ 0
+ x[3] ≥ 0
+ 1 - x[3] ≥ 0
+ x[4] ≥ 0
+ 1 - x[4] ≥ 0
+ x[5] ≥ 0
+ 1 - x[5] ≥ 0
+ 40 - 4*x[5] - 7*x[4] - 11*x[3] - 12*x[2] - 10*x[1] ≥ 0
+

We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.

import Clarabel
+solver = Clarabel.Optimizer
Clarabel.MOIwrapper.Optimizer

A Sum-of-Squares certificate that $p \ge \alpha$ over the domain S, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.

function solve(d)
+    model = SOSModel(solver)
+    @variable(model, α)
+    @objective(model, Max, α)
+    @constraint(model, c, p >= α, domain = K, maxdegree = d)
+    optimize!(model)
+    println(solution_summary(model))
+    return model
+end
solve (generic function with 1 method)

The first level of the hierarchy does not give any lower bound:

model2 = solve(2)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 33
+  constraints   = 53
+  nnz(P)        = 0
+  nnz(A)        = 75
+  cones (total) = 3
+    : Zero        = 1,  numel = 21
+    : Nonnegative = 1,  numel = 11
+    : PSDTriangle = 1,  numel = 21
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0  -1.5207e+02  -1.5207e+02  0.00e+00  5.27e-01  7.37e-02  1.00e+00  9.59e+01   ------
+  1   2.4388e+04   2.5071e+04  2.80e-02  7.15e-02  1.04e-02  6.91e+02  1.14e+01  9.66e-01
+  2   1.6512e+05   1.7080e+05  3.44e-02  3.79e-03  5.18e-04  5.68e+03  6.86e-01  9.47e-01
+  3   1.6216e+07   1.7985e+07  1.09e-01  7.36e-04  1.00e-04  1.77e+06  1.34e-01  8.78e-01
+  4   1.6199e+09   1.8067e+09  1.15e-01  1.41e-05  1.91e-06  1.87e+08  2.55e-03  9.81e-01
+  5   1.8390e+10   2.0786e+10  1.30e-01  2.05e-07  2.78e-08  2.40e+09  3.71e-05  9.86e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = primal infeasible
+solve time = 1.53ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : INFEASIBLE
+  Message from the solver:
+  "PRIMAL_INFEASIBLE"
+
+* Candidate solution (result #1)
+  Primal status      : INFEASIBLE_POINT
+  Dual status        : INFEASIBILITY_CERTIFICATE
+  Objective value    : -1.83898e+10
+  Dual objective value : -2.07856e+10
+
+* Work counters
+  Solve time (sec)   : 1.52892e-03
+  Barrier iterations : 5

Indeed, as the constraints have degree 1 and their multipliers are SOS so they have an even degree, with maxdegree 2 we can only use degree 0 multipliers hence constants. The terms of maximal degree in resulting sum will therefore only be in -x' * Q * x/2 hence it is not SOS whatever is the value of the multipliers. Let's try with maxdegree 3 so that the multipliers can be quadratic. This second level is now feasible and gives a lower bound of -22.

model3 = solve(3)
-------------------------------------------------------------
+           Clarabel.jl v0.7.1  -  Clever Acronym
+                   (c) Paul Goulart
+                University of Oxford, 2022
+-------------------------------------------------------------
+
+problem:
+  variables     = 253
+  constraints   = 308
+  nnz(P)        = 0
+  nnz(A)        = 715
+  cones (total) = 13
+    : Zero        = 1,  numel = 56
+    : PSDTriangle = 12,  numel = (21,21,21,21,...,21)
+
+settings:
+  linear algebra: direct / qdldl, precision: Float64
+  max iter = 200, time limit = Inf,  max step = 0.990
+  tol_feas = 1.0e-08, tol_gap_abs = 1.0e-08, tol_gap_rel = 1.0e-08,
+  static reg : on, ϵ1 = 1.0e-08, ϵ2 = 4.9e-32
+  dynamic reg: on, ϵ = 1.0e-13, δ = 2.0e-07
+  iter refine: on, reltol = 1.0e-13, abstol = 1.0e-12,
+               max iter = 10, stop ratio = 5.0
+  equilibrate: on, min_scale = 1.0e-05, max_scale = 1.0e+05
+               max iter = 10
+
+iter    pcost        dcost       gap       pres      dres      k/t        μ       step
+---------------------------------------------------------------------------------------------
+  0  -1.3991e+01  -1.3991e+01  6.35e-16  3.32e-01  9.13e-02  1.00e+00  9.46e+00   ------
+  1   2.4255e+02   2.4996e+02  3.06e-02  1.45e-01  3.32e-02  8.38e+00  2.67e+00  9.00e-01
+  2   7.3705e+01   7.9821e+01  8.30e-02  5.20e-02  1.50e-02  6.48e+00  1.52e+00  6.49e-01
+  3   3.6450e+01   3.8243e+01  4.92e-02  1.15e-02  3.41e-03  1.86e+00  4.41e-01  7.97e-01
+  4   3.1397e+01   3.2740e+01  4.28e-02  6.37e-03  1.91e-03  1.39e+00  2.70e-01  6.34e-01
+  5   2.1768e+01   2.2034e+01  1.22e-02  1.23e-03  3.40e-04  2.75e-01  5.65e-02  8.06e-01
+  6   2.2259e+01   2.2326e+01  2.99e-03  4.09e-04  1.03e-04  6.95e-02  1.91e-02  8.17e-01
+  7   2.1905e+01   2.1925e+01  9.14e-04  1.28e-04  3.24e-05  2.10e-02  6.08e-03  7.38e-01
+  8   2.1973e+01   2.1978e+01  1.91e-04  4.09e-05  1.02e-05  4.52e-03  1.97e-03  9.90e-01
+  9   2.2000e+01   2.2000e+01  2.57e-06  5.82e-07  1.41e-07  6.11e-05  2.82e-05  9.90e-01
+ 10   2.2000e+01   2.2000e+01  2.82e-08  6.39e-09  1.55e-09  6.70e-07  3.09e-07  9.89e-01
+ 11   2.2000e+01   2.2000e+01  3.49e-10  7.90e-11  1.92e-11  8.30e-09  3.83e-09  9.88e-01
+---------------------------------------------------------------------------------------------
+Terminated with status = solved
+solve time = 16.3ms
+* Solver : Clarabel
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "SOLVED"
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : -2.20000e+01
+  Dual objective value : -2.20000e+01
+
+* Work counters
+  Solve time (sec)   : 1.63028e-02
+  Barrier iterations : 11

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Sparsity/sign_symmetry.ipynb b/previews/PR347/generated/Sparsity/sign_symmetry.ipynb new file mode 100644 index 000000000..5a79a2ef8 --- /dev/null +++ b/previews/PR347/generated/Sparsity/sign_symmetry.ipynb @@ -0,0 +1,227 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Sign symmetry" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Example 4 of [L09]\n", + "\n", + "[L09] Lofberg, Johan.\n", + "*Pre-and post-processing sum-of-squares programs in practice*.\n", + "IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃],)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:3]" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We would like to determine whether the following polynomial is a sum-of-squares." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1 + x₃² + x₁x₂ + x₂⁴ + x₁⁴", + "text/latex": "$$ 1 + x_{3}^{2} + x_{1}x_{2} + x_{2}^{4} + x_{1}^{4} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "poly = 1 + x[1]^4 + x[1] * x[2] + x[2]^4 + x[3]^2" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "In order to do this, we can solve the following Sum-of-Squares program." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: SDP solved\n", + "Primal objective value: 0.0000000e+00 \n", + "Dual objective value: 0.0000000e+00 \n", + "Relative primal infeasibility: 5.23e-17 \n", + "Relative dual infeasibility: 5.00e-11 \n", + "Real Relative Gap: 0.00e+00 \n", + "XZ Relative Gap: 1.00e-10 \n", + "DIMACS error measures: 7.85e-17 0.00e+00 5.00e-11 0.00e+00 0.00e+00 1.00e-10\n", + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 8.10e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 4.0878274e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 2.7225538e+01 \n", + "* Solver : CSDP\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"Problem solved to optimality.\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : 0.00000e+00\n", + " Dual objective value : 0.00000e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 4.58002e-04\n", + "\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "7-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:\n 1\n x₃\n x₂\n x₁\n x₂²\n x₁x₂\n x₁²" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = CSDP.Optimizer\n", + "using SumOfSquares\n", + "function sos_check(sparsity)\n", + " model = Model(solver)\n", + " con_ref = @constraint(model, poly in SOSCone(), sparsity = sparsity)\n", + " optimize!(model)\n", + " println(solution_summary(model))\n", + " return gram_matrix(con_ref)\n", + "end\n", + "\n", + "g = sos_check(Sparsity.NoPattern())\n", + "g.basis.monomials" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "As detailed in the Example 4 of [L09], we can exploit the *sign symmetry* of\n", + "the polynomial to decompose the large positive semidefinite matrix into smaller ones." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: SDP solved\n", + "Primal objective value: 0.0000000e+00 \n", + "Dual objective value: 0.0000000e+00 \n", + "Relative primal infeasibility: 7.46e-17 \n", + "Relative dual infeasibility: 5.00e-11 \n", + "Real Relative Gap: 0.00e+00 \n", + "XZ Relative Gap: 1.21e-10 \n", + "DIMACS error measures: 1.21e-16 0.00e+00 5.00e-11 0.00e+00 0.00e+00 1.21e-10\n", + "CSDP 6.2.0\n", + "This is a pure primal feasibility problem.\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 7.15e-01 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 4.7634216e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: 0.0000000e+00 Ad: 1.00e+00 Dobj: 3.5035802e+01 \n", + "* Solver : CSDP\n", + "\n", + "* Status\n", + " Result count : 1\n", + " Termination status : OPTIMAL\n", + " Message from the solver:\n", + " \"Problem solved to optimality.\"\n", + "\n", + "* Candidate solution (result #1)\n", + " Primal status : FEASIBLE_POINT\n", + " Dual status : FEASIBLE_POINT\n", + " Objective value : 0.00000e+00\n", + " Dual objective value : 0.00000e+00\n", + "\n", + "* Work counters\n", + " Solve time (sec) : 6.82116e-04\n", + "\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element Vector{DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}:\n [x₂, x₁]\n [x₃]\n [1, x₂², x₁x₂, x₁²]" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "g = sos_check(Sparsity.SignSymmetry())\n", + "monos = [sub.basis.monomials for sub in g.blocks]" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Sparsity/sign_symmetry.jl b/previews/PR347/generated/Sparsity/sign_symmetry.jl new file mode 100644 index 000000000..c83284fa5 --- /dev/null +++ b/previews/PR347/generated/Sparsity/sign_symmetry.jl @@ -0,0 +1,23 @@ +using DynamicPolynomials +@polyvar x[1:3] + +poly = 1 + x[1]^4 + x[1] * x[2] + x[2]^4 + x[3]^2 + +import CSDP +solver = CSDP.Optimizer +using SumOfSquares +function sos_check(sparsity) + model = Model(solver) + con_ref = @constraint(model, poly in SOSCone(), sparsity = sparsity) + optimize!(model) + println(solution_summary(model)) + return gram_matrix(con_ref) +end + +g = sos_check(Sparsity.NoPattern()) +g.basis.monomials + +g = sos_check(Sparsity.SignSymmetry()) +monos = [sub.basis.monomials for sub in g.blocks] + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Sparsity/sign_symmetry/index.html b/previews/PR347/generated/Sparsity/sign_symmetry/index.html new file mode 100644 index 000000000..96961b9c1 --- /dev/null +++ b/previews/PR347/generated/Sparsity/sign_symmetry/index.html @@ -0,0 +1,26 @@ + +Sign symmetry · SumOfSquares

Sign symmetry

Adapted from: Example 4 of [L09]

[L09] Lofberg, Johan. Pre-and post-processing sum-of-squares programs in practice. IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011.

using DynamicPolynomials
+@polyvar x[1:3]
(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃],)

We would like to determine whether the following polynomial is a sum-of-squares.

poly = 1 + x[1]^4 + x[1] * x[2] + x[2]^4 + x[3]^2

\[ 1 + x_{3}^{2} + x_{1}x_{2} + x_{2}^{4} + x_{1}^{4} \]

In order to do this, we can solve the following Sum-of-Squares program.

import CSDP
+solver = CSDP.Optimizer
+using SumOfSquares
+function sos_check(sparsity)
+    model = Model(solver)
+    con_ref = @constraint(model, poly in SOSCone(), sparsity = sparsity)
+    optimize!(model)
+    println(solution_summary(model))
+    return gram_matrix(con_ref)
+end
+
+g = sos_check(Sparsity.NoPattern())
+g.basis.monomials
7-element DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}:
+ 1
+ x₃
+ x₂
+ x₁
+ x₂²
+ x₁x₂
+ x₁²

As detailed in the Example 4 of [L09], we can exploit the sign symmetry of the polynomial to decompose the large positive semidefinite matrix into smaller ones.

g = sos_check(Sparsity.SignSymmetry())
+monos = [sub.basis.monomials for sub in g.blocks]
3-element Vector{DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}:
+ [x₂, x₁]
+ [x₃]
+ [1, x₂², x₁x₂, x₁²]

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Sparsity/term_sparsity.ipynb b/previews/PR347/generated/Sparsity/term_sparsity.ipynb new file mode 100644 index 000000000..8e926acc6 --- /dev/null +++ b/previews/PR347/generated/Sparsity/term_sparsity.ipynb @@ -0,0 +1,379 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Term sparsity" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Example 3.5 of [WML20b]\n", + "\n", + "[WML20a] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre.\n", + "*TSSOS: A Moment-SOS hierarchy that exploits term sparsity*.\n", + "arXiv preprint arXiv:1912.08899 (2020).\n", + "\n", + "[WML20b] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre.\n", + "*Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension*.\n", + "arXiv preprint arXiv:2003.03210 (2020)." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃],)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:3]" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We would like to find the minimum value of the polynomial" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "6x₃² - 2x₂x₃ + 3x₂² - 2x₁x₂ + x₁² - 54x₂x₃² + 18x₂²x₃ - 2x₁²x₂ + 142x₂²x₃² + 2x₁²x₂²", + "text/latex": "$$ 6x_{3}^{2} - 2x_{2}x_{3} + 3x_{2}^{2} - 2x_{1}x_{2} + x_{1}^{2} - 54x_{2}x_{3}^{2} + 18x_{2}^{2}x_{3} - 2x_{1}^{2}x_{2} + 142x_{2}^{2}x_{3}^{2} + 2x_{1}^{2}x_{2}^{2} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "poly = x[1]^2 - 2x[1]*x[2] + 3x[2]^2 - 2x[1]^2*x[2] + 2x[1]^2*x[2]^2 - 2x[2]*x[3] + 6x[3]^2 + 18x[2]^2*x[3] - 54x[2]*x[3]^2 + 142x[2]^2*x[3]^2" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "The minimum value of the polynomial can be found to be zero." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: SDP solved\n", + "Primal objective value: 0.0000000e+00 \n", + "Dual objective value: 0.0000000e+00 \n", + "Relative primal infeasibility: 1.37e-16 \n", + "Relative dual infeasibility: 5.00e-11 \n", + "Real Relative Gap: 0.00e+00 \n", + "XZ Relative Gap: 1.34e-10 \n", + "DIMACS error measures: 2.22e-16 0.00e+00 8.34e-11 0.00e+00 0.00e+00 1.34e-10\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.71e-01 Pobj: -2.4909930e+02 Ad: 8.28e-01 Dobj: 7.2430886e+02 \n", + "Iter: 2 Ap: 9.99e-01 Pobj: -1.6816542e+02 Ad: 9.32e-01 Dobj: 1.6018799e+02 \n", + "Iter: 3 Ap: 9.96e-01 Pobj: -6.7497004e+00 Ad: 9.25e-01 Dobj: 6.1375873e+01 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -1.4716962e+00 Ad: 9.01e-01 Dobj: 8.9499288e+00 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -5.0539108e-01 Ad: 7.90e-01 Dobj: 2.7968144e+00 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -1.5435947e-01 Ad: 7.76e-01 Dobj: 8.7592257e-01 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -4.8636321e-02 Ad: 8.12e-01 Dobj: 2.4142234e-01 \n", + "Iter: 8 Ap: 1.00e+00 Pobj: -1.2922848e-02 Ad: 8.39e-01 Dobj: 6.6305594e-02 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -1.7072848e-03 Ad: 1.00e+00 Dobj: 1.0868111e-02 \n", + "Iter: 10 Ap: 1.00e+00 Pobj: -2.4483498e-04 Ad: 1.00e+00 Dobj: 7.6368904e-04 \n", + "Iter: 11 Ap: 9.96e-01 Pobj: -7.3630797e-06 Ad: 1.00e+00 Dobj: -4.5695805e-05 \n", + "Iter: 12 Ap: 9.97e-01 Pobj: -2.2399998e-07 Ad: 1.00e+00 Dobj: -7.5981645e-05 \n", + "Iter: 13 Ap: 1.00e+00 Pobj: -9.6673790e-09 Ad: 1.00e+00 Dobj: -5.0105891e-06 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-3.0595970201829914e-10" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = CSDP.Optimizer\n", + "using SumOfSquares\n", + "function sos_min(sparsity)\n", + " model = Model(solver)\n", + " @variable(model, t)\n", + " @objective(model, Max, t)\n", + " con_ref = @constraint(model, poly - t in SOSCone(), sparsity = sparsity)\n", + " optimize!(model)\n", + " return value(t), moment_matrix(con_ref)\n", + "end\n", + "\n", + "bound, ν = sos_min(Sparsity.NoPattern())\n", + "bound" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We find the corresponding minimizer `(0, 0, 0)` by matching the moments\n", + "of the moment matrix with a dirac measure centered at this minimizer." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Atomic measure on the variables x[1], x[2], x[3] with 1 atoms:\n at [2.0746447230887095e-6, 1.2388333204462911e-6, 2.309436069285367e-8] with weight 1.000000001500564" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "atomic_measure(ν, 1e-6)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We can see below that the basis contained 6 monomials hence we needed to use 6x6 PSD matrix variables." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MonomialBasis([1, x₃, x₂, x₁, x₂x₃, x₁x₂])" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "ν.basis" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Using the monomial/term sparsity method of [WML20a] based on cluster completion, we find the same bound." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 14 Ap: 9.68e-01 Pobj: -3.0595970e-10 Ad: 9.70e-01 Dobj: -2.0389137e-07 \n", + "Success: SDP solved\n", + "Primal objective value: -3.0595970e-10 \n", + "Dual objective value: -2.0389137e-07 \n", + "Relative primal infeasibility: 7.28e-14 \n", + "Relative dual infeasibility: 1.56e-09 \n", + "Real Relative Gap: -2.04e-07 \n", + "XZ Relative Gap: 2.88e-09 \n", + "DIMACS error measures: 7.85e-14 0.00e+00 2.58e-09 0.00e+00 -2.04e-07 2.88e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.71e-01 Pobj: -2.4909930e+02 Ad: 8.28e-01 Dobj: 7.2430886e+02 \n", + "Iter: 2 Ap: 9.99e-01 Pobj: -1.6816542e+02 Ad: 9.32e-01 Dobj: 1.6018799e+02 \n", + "Iter: 3 Ap: 9.96e-01 Pobj: -6.7497004e+00 Ad: 9.25e-01 Dobj: 6.1375873e+01 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -1.4716962e+00 Ad: 9.01e-01 Dobj: 8.9499288e+00 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -5.0539108e-01 Ad: 7.90e-01 Dobj: 2.7968144e+00 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -1.5435947e-01 Ad: 7.76e-01 Dobj: 8.7592257e-01 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -4.8636321e-02 Ad: 8.12e-01 Dobj: 2.4142234e-01 \n", + "Iter: 8 Ap: 1.00e+00 Pobj: -1.2922848e-02 Ad: 8.39e-01 Dobj: 6.6305594e-02 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -1.7072848e-03 Ad: 1.00e+00 Dobj: 1.0868111e-02 \n", + "Iter: 10 Ap: 1.00e+00 Pobj: -2.4483498e-04 Ad: 1.00e+00 Dobj: 7.6368904e-04 \n", + "Iter: 11 Ap: 9.96e-01 Pobj: -7.3630797e-06 Ad: 1.00e+00 Dobj: -4.5695805e-05 \n", + "Iter: 12 Ap: 9.97e-01 Pobj: -2.2399998e-07 Ad: 1.00e+00 Dobj: -7.5981645e-05 \n", + "Iter: 13 Ap: 1.00e+00 Pobj: -9.6673790e-09 Ad: 1.00e+00 Dobj: -5.0105891e-06 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-3.0595970201829914e-10" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "bound, ν = sos_min(Sparsity.Monomial())\n", + "bound" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "Which is not suprising as no sparsity reduction could be performed." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1-element Vector{MonomialBasis{DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}}:\n MonomialBasis([1, x₃, x₂, x₁, x₂x₃, x₁x₂])" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "[sub.basis for sub in ν.blocks]" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "Using the monomial/term sparsity method of [WML20b] based on chordal completion, the lower bound is smaller than 0." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 14 Ap: 9.68e-01 Pobj: -3.0595970e-10 Ad: 9.70e-01 Dobj: -2.0389137e-07 \n", + "Success: SDP solved\n", + "Primal objective value: -3.0595970e-10 \n", + "Dual objective value: -2.0389137e-07 \n", + "Relative primal infeasibility: 7.28e-14 \n", + "Relative dual infeasibility: 1.56e-09 \n", + "Real Relative Gap: -2.04e-07 \n", + "XZ Relative Gap: 2.88e-09 \n", + "DIMACS error measures: 7.85e-14 0.00e+00 2.58e-09 0.00e+00 -2.04e-07 2.88e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 9.27e-01 Pobj: -1.4689079e+02 Ad: 8.89e-01 Dobj: 9.8435236e+02 \n", + "Iter: 2 Ap: 7.48e-01 Pobj: -1.1657123e+02 Ad: 8.75e-01 Dobj: 2.5250977e+02 \n", + "Iter: 3 Ap: 9.36e-01 Pobj: -3.9438731e+01 Ad: 6.27e-01 Dobj: 1.9098284e+02 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -5.2243839e+00 Ad: 8.90e-01 Dobj: 5.7737377e+01 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -1.9667022e+00 Ad: 9.46e-01 Dobj: 9.3864604e+00 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -6.0952393e-01 Ad: 8.98e-01 Dobj: 2.7249453e+00 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -1.8828026e-01 Ad: 7.05e-01 Dobj: 1.1095449e+00 \n", + "Iter: 8 Ap: 1.00e+00 Pobj: -8.2145391e-02 Ad: 7.76e-01 Dobj: 3.4962777e-01 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -3.5569922e-02 Ad: 9.13e-01 Dobj: 6.3372767e-02 \n", + "Iter: 10 Ap: 1.00e+00 Pobj: -1.3602383e-02 Ad: 1.00e+00 Dobj: 9.0938016e-03 \n", + "Iter: 11 Ap: 1.00e+00 Pobj: -7.2782376e-03 Ad: 1.00e+00 Dobj: 7.3762428e-04 \n", + "Iter: 12 Ap: 1.00e+00 Pobj: -4.9359857e-03 Ad: 1.00e+00 Dobj: -2.5754966e-03 \n", + "Iter: 13 Ap: 1.00e+00 Pobj: -3.8914064e-03 Ad: 1.00e+00 Dobj: -3.3743286e-03 \n", + "Iter: 14 Ap: 1.00e+00 Pobj: -3.6046296e-03 Ad: 1.00e+00 Dobj: -3.5789356e-03 \n", + "Iter: 15 Ap: 1.00e+00 Pobj: -3.5547289e-03 Ad: 1.00e+00 Dobj: -3.6075822e-03 \n", + "Iter: 16 Ap: 1.00e+00 Pobj: -3.5514644e-03 Ad: 1.00e+00 Dobj: -3.5795009e-03 \n", + "Iter: 17 Ap: 1.00e+00 Pobj: -3.5512133e-03 Ad: 9.80e-01 Dobj: -3.5523286e-03 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-0.0035511999768404467" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "bound, ν = sos_min(Sparsity.Monomial(ChordalCompletion()))\n", + "bound" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "However, this bound was obtained with an SDP with 4 matrices of size 3x3." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "4-element Vector{MonomialBasis{DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}}:\n MonomialBasis([x₂, x₁, x₁x₂])\n MonomialBasis([x₂, x₂x₃, x₁x₂])\n MonomialBasis([x₃, x₂, x₂x₃])\n MonomialBasis([1, x₂x₃, x₁x₂])" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "[sub.basis for sub in ν.blocks]" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Sparsity/term_sparsity.jl b/previews/PR347/generated/Sparsity/term_sparsity.jl new file mode 100644 index 000000000..c5fdd5105 --- /dev/null +++ b/previews/PR347/generated/Sparsity/term_sparsity.jl @@ -0,0 +1,35 @@ +using DynamicPolynomials +@polyvar x[1:3] + +poly = x[1]^2 - 2x[1]*x[2] + 3x[2]^2 - 2x[1]^2*x[2] + 2x[1]^2*x[2]^2 - 2x[2]*x[3] + 6x[3]^2 + 18x[2]^2*x[3] - 54x[2]*x[3]^2 + 142x[2]^2*x[3]^2 + +import CSDP +solver = CSDP.Optimizer +using SumOfSquares +function sos_min(sparsity) + model = Model(solver) + @variable(model, t) + @objective(model, Max, t) + con_ref = @constraint(model, poly - t in SOSCone(), sparsity = sparsity) + optimize!(model) + return value(t), moment_matrix(con_ref) +end + +bound, ν = sos_min(Sparsity.NoPattern()) +bound + +atomic_measure(ν, 1e-6) + +ν.basis + +bound, ν = sos_min(Sparsity.Monomial()) +bound + +[sub.basis for sub in ν.blocks] + +bound, ν = sos_min(Sparsity.Monomial(ChordalCompletion())) +bound + +[sub.basis for sub in ν.blocks] + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Sparsity/term_sparsity/index.html b/previews/PR347/generated/Sparsity/term_sparsity/index.html new file mode 100644 index 000000000..15c0969b3 --- /dev/null +++ b/previews/PR347/generated/Sparsity/term_sparsity/index.html @@ -0,0 +1,24 @@ + +Term sparsity · SumOfSquares

Term sparsity

Adapted from: Example 3.5 of [WML20b]

[WML20a] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. TSSOS: A Moment-SOS hierarchy that exploits term sparsity. arXiv preprint arXiv:1912.08899 (2020).

[WML20b] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension. arXiv preprint arXiv:2003.03210 (2020).

using DynamicPolynomials
+@polyvar x[1:3]
(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃],)

We would like to find the minimum value of the polynomial

poly = x[1]^2 - 2x[1]*x[2] + 3x[2]^2 - 2x[1]^2*x[2] + 2x[1]^2*x[2]^2 - 2x[2]*x[3] + 6x[3]^2 + 18x[2]^2*x[3] - 54x[2]*x[3]^2 + 142x[2]^2*x[3]^2

\[ 6x_{3}^{2} - 2x_{2}x_{3} + 3x_{2}^{2} - 2x_{1}x_{2} + x_{1}^{2} - 54x_{2}x_{3}^{2} + 18x_{2}^{2}x_{3} - 2x_{1}^{2}x_{2} + 142x_{2}^{2}x_{3}^{2} + 2x_{1}^{2}x_{2}^{2} \]

The minimum value of the polynomial can be found to be zero.

import CSDP
+solver = CSDP.Optimizer
+using SumOfSquares
+function sos_min(sparsity)
+    model = Model(solver)
+    @variable(model, t)
+    @objective(model, Max, t)
+    con_ref = @constraint(model, poly - t in SOSCone(), sparsity = sparsity)
+    optimize!(model)
+    return value(t), moment_matrix(con_ref)
+end
+
+bound, ν = sos_min(Sparsity.NoPattern())
+bound
-3.0595970201829914e-10

We find the corresponding minimizer (0, 0, 0) by matching the moments of the moment matrix with a dirac measure centered at this minimizer.

atomic_measure(ν, 1e-6)
Atomic measure on the variables x[1], x[2], x[3] with 1 atoms:
+ at [2.0746447230887095e-6, 1.2388333204462911e-6, 2.309436069285367e-8] with weight 1.000000001500564

We can see below that the basis contained 6 monomials hence we needed to use 6x6 PSD matrix variables.

ν.basis
MonomialBasis([1, x₃, x₂, x₁, x₂x₃, x₁x₂])

Using the monomial/term sparsity method of [WML20a] based on cluster completion, we find the same bound.

bound, ν = sos_min(Sparsity.Monomial())
+bound
-3.0595970201829914e-10

Which is not suprising as no sparsity reduction could be performed.

[sub.basis for sub in ν.blocks]
1-element Vector{MonomialBasis{DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}}:
+ MonomialBasis([1, x₃, x₂, x₁, x₂x₃, x₁x₂])

Using the monomial/term sparsity method of [WML20b] based on chordal completion, the lower bound is smaller than 0.

bound, ν = sos_min(Sparsity.Monomial(ChordalCompletion()))
+bound
-0.0035511999768404467

However, this bound was obtained with an SDP with 4 matrices of size 3x3.

[sub.basis for sub in ν.blocks]
4-element Vector{MonomialBasis{DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}, DynamicPolynomials.MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}}:
+ MonomialBasis([x₂, x₁, x₁x₂])
+ MonomialBasis([x₂, x₂x₃, x₁x₂])
+ MonomialBasis([x₃, x₂, x₂x₃])
+ MonomialBasis([1, x₂x₃, x₁x₂])

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Symmetry/cyclic.ipynb b/previews/PR347/generated/Symmetry/cyclic.ipynb new file mode 100644 index 000000000..e92e9103c --- /dev/null +++ b/previews/PR347/generated/Symmetry/cyclic.ipynb @@ -0,0 +1,490 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Cyclic symmetry for Sums of Hermitian Squares" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We start by defining the Cyclic group." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using GroupsCore\n", + "import PermutationGroups\n", + "\n", + "struct CyclicElem <: GroupElement\n", + " n::Int\n", + " id::Int\n", + "end\n", + "Base.:(==)(a::CyclicElem, b::CyclicElem) = a.n == b.n && a.id == b.id\n", + "Base.inv(el::CyclicElem) = CyclicElem(el.n, (el.n - el.id) % el.n)\n", + "\n", + "function Base.:*(a::CyclicElem, b::CyclicElem)\n", + " return CyclicElem(a.n, (a.id + b.id) % a.n)\n", + "end\n", + "Base.:^(el::CyclicElem, k::Integer) = CyclicElem(el.n, (el.id * k) % el.n)\n", + "\n", + "Base.conj(a::CyclicElem, b::CyclicElem) = inv(b) * a * b\n", + "Base.:^(a::CyclicElem, b::CyclicElem) = conj(a, b)\n", + "\n", + "function PermutationGroups.order(el::CyclicElem)\n", + " return div(el.n, gcd(el.n, el.id))\n", + "end\n", + "\n", + "struct CyclicGroup <: Group\n", + " n::Int\n", + "end\n", + "Base.eltype(::CyclicGroup) = CyclicElem\n", + "Base.one(c::Union{CyclicGroup, CyclicElem}) = CyclicElem(c.n, 0)\n", + "PermutationGroups.gens(c::CyclicGroup) = [CyclicElem(c.n, 1)]\n", + "PermutationGroups.order(::Type{T}, c::CyclicGroup) where {T} = convert(T, c.n)\n", + "function Base.iterate(c::CyclicGroup, prev::CyclicElem=CyclicElem(c.n, -1))\n", + " id = prev.id + 1\n", + " if id >= c.n\n", + " return nothing\n", + " else\n", + " next = CyclicElem(c.n, id)\n", + " return next, next\n", + " end\n", + "end" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "Now we define that the cyclic group acts on monomial by permuting variables\n", + "cyclically. So for instance, `CyclicElem(3, 1)` would transform\n", + "`x_1^3*x_2*x_3^4` into `x_1^4*x_2^3*x_3`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "x₁⁴x₂³x₃", + "text/latex": "$$ x_{1}^{4}x_{2}^{3}x_{3} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "import MultivariatePolynomials as MP\n", + "\n", + "using SumOfSquares\n", + "\n", + "struct Action{V<:MP.AbstractVariable} <: Symmetry.OnMonomials\n", + " variables::Vector{V}\n", + "end\n", + "Symmetry.SymbolicWedderburn.coeff_type(::Action) = Float64\n", + "function Symmetry.SymbolicWedderburn.action(a::Action, el::CyclicElem, mono::MP.AbstractMonomial)\n", + " return prod(MP.powers(mono), init=MP.constant_monomial(mono)) do (var, exp)\n", + " index = findfirst(isequal(var), a.variables)\n", + " new_index = mod1(index + el.id, el.n)\n", + " return a.variables[new_index]^exp\n", + " end\n", + "end\n", + "\n", + "using DynamicPolynomials\n", + "@polyvar x[1:3]\n", + "action = Action(x)\n", + "g = CyclicElem(3, 1)\n", + "Symmetry.SymbolicWedderburn.action(action, g, x[1]^3 * x[2] * x[3]^4)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "The following polynomial `poly` is invariant under the action of the group `G`." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "x₃² + x₂x₃ + x₂² + x₁x₃ + x₁x₂ + x₁²", + "text/latex": "$$ x_{3}^{2} + x_{2}x_{3} + x_{2}^{2} + x_{1}x_{3} + x_{1}x_{2} + x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "N = 3\n", + "G = CyclicGroup(N)\n", + "poly = sum(x[i] * x[mod1(i + 1, N)] for i in 1:N) + sum(x.^2)\n", + "Symmetry.SymbolicWedderburn.action(action, g, poly)" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Let's now find the minimum of `p` by exploiting this symmetry." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 18 Ap: 9.59e-01 Pobj: -3.5512000e-03 Ad: 9.59e-01 Dobj: -3.5512523e-03 \n", + "Success: SDP solved\n", + "Primal objective value: -3.5512000e-03 \n", + "Dual objective value: -3.5512523e-03 \n", + "Relative primal infeasibility: 1.17e-13 \n", + "Relative dual infeasibility: 5.36e-10 \n", + "Real Relative Gap: -5.20e-08 \n", + "XZ Relative Gap: 1.22e-09 \n", + "DIMACS error measures: 1.26e-13 0.00e+00 1.44e-09 0.00e+00 -5.20e-08 1.22e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 1.00e+00 Pobj: -6.8633327e+00 Ad: 9.00e-01 Dobj: 1.9835999e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: -2.8142041e+00 Ad: 9.00e-01 Dobj: 3.4715380e+00 \n", + "Iter: 3 Ap: 1.00e+00 Pobj: -1.5335395e-02 Ad: 9.00e-01 Dobj: 4.1414777e-01 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -2.4302191e-05 Ad: 1.00e+00 Dobj: 4.4865070e-05 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -7.8953240e-07 Ad: 1.00e+00 Dobj: -1.2669850e-06 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -5.8902884e-08 Ad: 1.00e+00 Dobj: -5.8810369e-07 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -8.1684162e-09 Ad: 1.00e+00 Dobj: 1.9520853e-09 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 2.22045e-16\n Dual objective value : -2.20229e-10\n\n* Work counters\n Solve time (sec) : 1.06096e-03\n" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = CSDP.Optimizer\n", + "model = Model(solver)\n", + "@variable(model, t)\n", + "@objective(model, Max, t)\n", + "pattern = Symmetry.Pattern(G, action)\n", + "con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\n", + "optimize!(model)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Let's look at the symmetry adapted basis used." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[1.0, -0.5773502691896257x₃ - 0.5773502691896257x₂ - 0.5773502691896257x₁]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-0.816496580927726x₃ + 0.4082482904638631x₂ + 0.4082482904638631x₁]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-0.7071067811865477x₂ + 0.7071067811865477x₁]\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": "2×2 SymMatrix{Float64}:\n 1.07382e-17 0.0\n 0.0 2.0" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": "1×1 SymMatrix{Float64}:\n 0.4999999999999981" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": "1×1 SymMatrix{Float64}:\n 0.4999999999999981" + }, + "metadata": {} + } + ], + "cell_type": "code", + "source": [ + "for gram in gram_matrix(con_ref).blocks\n", + " println(gram.basis.polynomials)\n", + " display(gram.Q)\n", + "end" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Let's look into more details at the last two elements of the basis." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:\n -0.8164965809277261x₃ + 0.4082482904638631x₂ + 0.4082482904638631x₁\n -0.7071067811865475x₂ + 0.7071067811865475x₁" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "basis = [(x[1] + x[2] - 2x[3])/√6, (x[1] - x[2])/√2]" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "This actually constitutes the basis for an invariant subspace corresponding\n", + "to a group character of degree 2 and multiplicity 1.\n", + "This means that it decomposes the semidefinite matrix into 2 blocks of size\n", + "1-by-1 that are equal. Indeed, we see above that `gram.Q` is identically equal for both.\n", + "As the group is generated by one element `g`, we can just verify it by verifying\n", + "its invariance under `g`.\n", + "The image of each element under the basis is:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:\n 0.4082482904638631x₃ + 0.4082482904638631x₂ - 0.8164965809277261x₁\n -0.7071067811865475x₃ + 0.7071067811865475x₂" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "image = [Symmetry.SymbolicWedderburn.action(action, g, p) for p in basis]" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "We can see that they are both still in the same 2-dimensional subspace." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:\n 0.4082482904638631x₃ + 0.4082482904638629x₂ - 0.816496580927726x₁\n -0.7071067811865476x₃ + 0.7071067811865475x₂ + 5.551115123125783e-17x₁" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "a = -1/2\n", + "b = √3/2\n", + "[a -b; b a] * basis" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "In fact, these last two basis comes from the real decomposition of a complex one." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 8 Ap: 1.00e+00 Pobj: 2.2204460e-16 Ad: 9.00e-01 Dobj: -2.2022945e-10 \n", + "Success: SDP solved\n", + "Primal objective value: 2.2204460e-16 \n", + "Dual objective value: -2.2022945e-10 \n", + "Relative primal infeasibility: 8.86e-16 \n", + "Relative dual infeasibility: 3.82e-10 \n", + "Real Relative Gap: -2.20e-10 \n", + "XZ Relative Gap: 2.29e-09 \n", + "DIMACS error measures: 1.53e-15 0.00e+00 7.89e-10 0.00e+00 -2.20e-10 2.29e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 1.00e+00 Pobj: -8.9892401e+00 Ad: 9.07e-01 Dobj: 4.8627163e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: -5.4165963e+00 Ad: 9.18e-01 Dobj: 1.0591774e+01 \n", + "Iter: 3 Ap: 1.00e+00 Pobj: -6.3166907e-01 Ad: 8.98e-01 Dobj: 3.0288603e+00 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -4.2564141e-02 Ad: 9.09e-01 Dobj: 3.9201832e-01 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -4.3454962e-03 Ad: 9.28e-01 Dobj: 4.0461107e-02 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -4.2815474e-04 Ad: 9.34e-01 Dobj: 3.8633036e-03 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -4.3920196e-05 Ad: 9.88e-01 Dobj: 1.7392285e-04 \n", + "Iter: 8 Ap: 1.00e+00 Pobj: -2.3698636e-06 Ad: 9.99e-01 Dobj: 4.5447245e-06 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -9.4705116e-08 Ad: 1.00e+00 Dobj: -2.3966141e-06 \n", + "Iter: 10 Ap: 1.00e+00 Pobj: -4.0174413e-09 Ad: 9.69e-01 Dobj: -9.9538646e-08 \n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, ComplexF64}[(1.0 - 0.0im), (-0.5773502691896257 - 0.0im)x₃ + (-0.5773502691896257 - 0.0im)x₂ + (-0.5773502691896257 - 0.0im)x₁]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, ComplexF64}[(-0.577350269189626 - 0.0im)x₃ + (0.2886751345948128 + 0.5000000000000001im)x₂ + (0.28867513459481314 - 0.49999999999999994im)x₁]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, ComplexF64}[(-0.577350269189626 - 0.0im)x₃ + (0.28867513459481314 - 0.49999999999999994im)x₂ + (0.2886751345948128 + 0.5000000000000001im)x₁]\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": "2×2 VectorizedHermitianMatrix{ComplexF64, Float64, ComplexF64}:\n 1.67745e-10+0.0im 0.0+0.0im\n 0.0+0.0im 2.0+0.0im" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": "1×1 VectorizedHermitianMatrix{ComplexF64, Float64, ComplexF64}:\n 0.5000000408028554 + 0.0im" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": "1×1 VectorizedHermitianMatrix{ComplexF64, Float64, ComplexF64}:\n 0.4999999591971749 + 0.0im" + }, + "metadata": {} + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = CSDP.Optimizer\n", + "model = Model(solver)\n", + "@variable(model, t)\n", + "@objective(model, Max, t)\n", + "pattern = Symmetry.Pattern(G, action)\n", + "cone = SumOfSquares.NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}()\n", + "con_ref = @constraint(model, poly - t in cone, symmetry = pattern)\n", + "optimize!(model)\n", + "solution_summary(model)\n", + "\n", + "for gram in gram_matrix(con_ref).blocks\n", + " println(gram.basis.polynomials)\n", + " display(gram.Q)\n", + "end" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "We can see that the real invariant subspace was in fact coming from two complex conjugate complex invariant subspaces:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(0.4082482904638631 - 0.7071067811865475im)x₃ + (0.4082482904638631 + 0.7071067811865475im)x₂ + (-0.8164965809277261 + 0.0im)x₁", + "text/latex": "$$ (0.4082482904638631 - 0.7071067811865475im)x_{3} + (0.4082482904638631 + 0.7071067811865475im)x_{2} + (-0.8164965809277261 + 0.0im)x_{1} $$" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "complex_basis = basis[1] + im * basis[2]\n", + "image = Symmetry.SymbolicWedderburn.action(action, g, complex_basis)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "And there is a direct correspondance between the representation of the real and complex versions:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(0.4082482904638631 - 0.7071067811865476im)x₃ + (0.4082482904638629 + 0.7071067811865475im)x₂ + (-0.816496580927726 + 5.551115123125783e-17im)x₁", + "text/latex": "$$ (0.4082482904638631 - 0.7071067811865476im)x_{3} + (0.4082482904638629 + 0.7071067811865475im)x_{2} + (-0.816496580927726 + 5.551115123125783e-17im)x_{1} $$" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "(a + b * im) * complex_basis" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Symmetry/cyclic.jl b/previews/PR347/generated/Symmetry/cyclic.jl new file mode 100644 index 000000000..b5f2aa604 --- /dev/null +++ b/previews/PR347/generated/Symmetry/cyclic.jl @@ -0,0 +1,111 @@ +using GroupsCore +import PermutationGroups + +struct CyclicElem <: GroupElement + n::Int + id::Int +end +Base.:(==)(a::CyclicElem, b::CyclicElem) = a.n == b.n && a.id == b.id +Base.inv(el::CyclicElem) = CyclicElem(el.n, (el.n - el.id) % el.n) + +function Base.:*(a::CyclicElem, b::CyclicElem) + return CyclicElem(a.n, (a.id + b.id) % a.n) +end +Base.:^(el::CyclicElem, k::Integer) = CyclicElem(el.n, (el.id * k) % el.n) + +Base.conj(a::CyclicElem, b::CyclicElem) = inv(b) * a * b +Base.:^(a::CyclicElem, b::CyclicElem) = conj(a, b) + +function PermutationGroups.order(el::CyclicElem) + return div(el.n, gcd(el.n, el.id)) +end + +struct CyclicGroup <: Group + n::Int +end +Base.eltype(::CyclicGroup) = CyclicElem +Base.one(c::Union{CyclicGroup, CyclicElem}) = CyclicElem(c.n, 0) +PermutationGroups.gens(c::CyclicGroup) = [CyclicElem(c.n, 1)] +PermutationGroups.order(::Type{T}, c::CyclicGroup) where {T} = convert(T, c.n) +function Base.iterate(c::CyclicGroup, prev::CyclicElem=CyclicElem(c.n, -1)) + id = prev.id + 1 + if id >= c.n + return nothing + else + next = CyclicElem(c.n, id) + return next, next + end +end + +import MultivariatePolynomials as MP + +using SumOfSquares + +struct Action{V<:MP.AbstractVariable} <: Symmetry.OnMonomials + variables::Vector{V} +end +Symmetry.SymbolicWedderburn.coeff_type(::Action) = Float64 +function Symmetry.SymbolicWedderburn.action(a::Action, el::CyclicElem, mono::MP.AbstractMonomial) + return prod(MP.powers(mono), init=MP.constant_monomial(mono)) do (var, exp) + index = findfirst(isequal(var), a.variables) + new_index = mod1(index + el.id, el.n) + return a.variables[new_index]^exp + end +end + +using DynamicPolynomials +@polyvar x[1:3] +action = Action(x) +g = CyclicElem(3, 1) +Symmetry.SymbolicWedderburn.action(action, g, x[1]^3 * x[2] * x[3]^4) + +N = 3 +G = CyclicGroup(N) +poly = sum(x[i] * x[mod1(i + 1, N)] for i in 1:N) + sum(x.^2) +Symmetry.SymbolicWedderburn.action(action, g, poly) + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, action) +con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) +optimize!(model) +solution_summary(model) + +for gram in gram_matrix(con_ref).blocks + println(gram.basis.polynomials) + display(gram.Q) +end + +basis = [(x[1] + x[2] - 2x[3])/√6, (x[1] - x[2])/√2] + +image = [Symmetry.SymbolicWedderburn.action(action, g, p) for p in basis] + +a = -1/2 +b = √3/2 +[a -b; b a] * basis + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, action) +cone = SumOfSquares.NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}() +con_ref = @constraint(model, poly - t in cone, symmetry = pattern) +optimize!(model) +solution_summary(model) + +for gram in gram_matrix(con_ref).blocks + println(gram.basis.polynomials) + display(gram.Q) +end + +complex_basis = basis[1] + im * basis[2] +image = Symmetry.SymbolicWedderburn.action(action, g, complex_basis) + +(a + b * im) * complex_basis + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Symmetry/cyclic/index.html b/previews/PR347/generated/Symmetry/cyclic/index.html new file mode 100644 index 000000000..01fd23ca7 --- /dev/null +++ b/previews/PR347/generated/Symmetry/cyclic/index.html @@ -0,0 +1,137 @@ + +Cyclic symmetry for Sums of Hermitian Squares · SumOfSquares

Cyclic symmetry for Sums of Hermitian Squares

We start by defining the Cyclic group.

using GroupsCore
+import PermutationGroups
+
+struct CyclicElem <: GroupElement
+    n::Int
+    id::Int
+end
+Base.:(==)(a::CyclicElem, b::CyclicElem) = a.n == b.n && a.id == b.id
+Base.inv(el::CyclicElem) = CyclicElem(el.n, (el.n - el.id) % el.n)
+
+function Base.:*(a::CyclicElem, b::CyclicElem)
+    return CyclicElem(a.n, (a.id + b.id) % a.n)
+end
+Base.:^(el::CyclicElem, k::Integer) = CyclicElem(el.n, (el.id * k) % el.n)
+
+Base.conj(a::CyclicElem, b::CyclicElem) = inv(b) * a * b
+Base.:^(a::CyclicElem, b::CyclicElem) = conj(a, b)
+
+function PermutationGroups.order(el::CyclicElem)
+    return div(el.n, gcd(el.n, el.id))
+end
+
+struct CyclicGroup <: Group
+    n::Int
+end
+Base.eltype(::CyclicGroup) = CyclicElem
+Base.one(c::Union{CyclicGroup, CyclicElem}) = CyclicElem(c.n, 0)
+PermutationGroups.gens(c::CyclicGroup) = [CyclicElem(c.n, 1)]
+PermutationGroups.order(::Type{T}, c::CyclicGroup) where {T} = convert(T, c.n)
+function Base.iterate(c::CyclicGroup, prev::CyclicElem=CyclicElem(c.n, -1))
+    id = prev.id + 1
+    if id >= c.n
+        return nothing
+    else
+        next = CyclicElem(c.n, id)
+        return next, next
+    end
+end

Now we define that the cyclic group acts on monomial by permuting variables cyclically. So for instance, CyclicElem(3, 1) would transform x_1^3*x_2*x_3^4 into x_1^4*x_2^3*x_3.

import MultivariatePolynomials as MP
+
+using SumOfSquares
+
+struct Action{V<:MP.AbstractVariable} <: Symmetry.OnMonomials
+    variables::Vector{V}
+end
+Symmetry.SymbolicWedderburn.coeff_type(::Action) = Float64
+function Symmetry.SymbolicWedderburn.action(a::Action, el::CyclicElem, mono::MP.AbstractMonomial)
+    return prod(MP.powers(mono), init=MP.constant_monomial(mono)) do (var, exp)
+        index = findfirst(isequal(var), a.variables)
+        new_index = mod1(index + el.id, el.n)
+        return a.variables[new_index]^exp
+    end
+end
+
+using DynamicPolynomials
+@polyvar x[1:3]
+action = Action(x)
+g = CyclicElem(3, 1)
+Symmetry.SymbolicWedderburn.action(action, g, x[1]^3 * x[2] * x[3]^4)

\[ x_{1}^{4}x_{2}^{3}x_{3} \]

The following polynomial poly is invariant under the action of the group G.

N = 3
+G = CyclicGroup(N)
+poly = sum(x[i] * x[mod1(i + 1, N)] for i in 1:N) + sum(x.^2)
+Symmetry.SymbolicWedderburn.action(action, g, poly)

\[ x_{3}^{2} + x_{2}x_{3} + x_{2}^{2} + x_{1}x_{3} + x_{1}x_{2} + x_{1}^{2} \]

Let's now find the minimum of p by exploiting this symmetry.

import CSDP
+solver = CSDP.Optimizer
+model = Model(solver)
+@variable(model, t)
+@objective(model, Max, t)
+pattern = Symmetry.Pattern(G, action)
+con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)
+optimize!(model)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 2.22045e-16
+  Dual objective value : -2.20229e-10
+
+* Work counters
+  Solve time (sec)   : 1.08004e-03
+

Let's look at the symmetry adapted basis used.

for gram in gram_matrix(con_ref).blocks
+    println(gram.basis.polynomials)
+    display(gram.Q)
+end
DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[1.0, -0.5773502691896257x₃ - 0.5773502691896257x₂ - 0.5773502691896257x₁]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-0.816496580927726x₃ + 0.4082482904638631x₂ + 0.4082482904638631x₁]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-0.7071067811865477x₂ + 0.7071067811865477x₁]

Let's look into more details at the last two elements of the basis.

basis = [(x[1] + x[2] - 2x[3])/√6, (x[1] - x[2])/√2]
2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:
+ -0.8164965809277261x₃ + 0.4082482904638631x₂ + 0.4082482904638631x₁
+ -0.7071067811865475x₂ + 0.7071067811865475x₁

This actually constitutes the basis for an invariant subspace corresponding to a group character of degree 2 and multiplicity 1. This means that it decomposes the semidefinite matrix into 2 blocks of size 1-by-1 that are equal. Indeed, we see above that gram.Q is identically equal for both. As the group is generated by one element g, we can just verify it by verifying its invariance under g. The image of each element under the basis is:

image = [Symmetry.SymbolicWedderburn.action(action, g, p) for p in basis]
2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:
+ 0.4082482904638631x₃ + 0.4082482904638631x₂ - 0.8164965809277261x₁
+ -0.7071067811865475x₃ + 0.7071067811865475x₂

We can see that they are both still in the same 2-dimensional subspace.

a = -1/2
+b = √3/2
+[a -b; b a] * basis
2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:
+ 0.4082482904638631x₃ + 0.4082482904638629x₂ - 0.816496580927726x₁
+ -0.7071067811865476x₃ + 0.7071067811865475x₂ + 5.551115123125783e-17x₁

In fact, these last two basis comes from the real decomposition of a complex one.

import CSDP
+solver = CSDP.Optimizer
+model = Model(solver)
+@variable(model, t)
+@objective(model, Max, t)
+pattern = Symmetry.Pattern(G, action)
+cone = SumOfSquares.NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}()
+con_ref = @constraint(model, poly - t in cone, symmetry = pattern)
+optimize!(model)
+solution_summary(model)
+
+for gram in gram_matrix(con_ref).blocks
+    println(gram.basis.polynomials)
+    display(gram.Q)
+end
Iter:  8 Ap: 1.00e+00 Pobj:  2.2204460e-16 Ad: 9.00e-01 Dobj: -2.2022945e-10
+Success: SDP solved
+Primal objective value: 2.2204460e-16
+Dual objective value: -2.2022945e-10
+Relative primal infeasibility: 8.86e-16
+Relative dual infeasibility: 3.82e-10
+Real Relative Gap: -2.20e-10
+XZ Relative Gap: 2.29e-09
+DIMACS error measures: 1.53e-15 0.00e+00 7.89e-10 0.00e+00 -2.20e-10 2.29e-09
+CSDP 6.2.0
+Iter:  0 Ap: 0.00e+00 Pobj:  0.0000000e+00 Ad: 0.00e+00 Dobj:  0.0000000e+00
+Iter:  1 Ap: 1.00e+00 Pobj: -8.9892401e+00 Ad: 9.07e-01 Dobj:  4.8627163e+01
+Iter:  2 Ap: 1.00e+00 Pobj: -5.4165963e+00 Ad: 9.18e-01 Dobj:  1.0591774e+01
+Iter:  3 Ap: 1.00e+00 Pobj: -6.3166907e-01 Ad: 8.98e-01 Dobj:  3.0288603e+00
+Iter:  4 Ap: 1.00e+00 Pobj: -4.2564141e-02 Ad: 9.09e-01 Dobj:  3.9201832e-01
+Iter:  5 Ap: 1.00e+00 Pobj: -4.3454962e-03 Ad: 9.28e-01 Dobj:  4.0461107e-02
+Iter:  6 Ap: 1.00e+00 Pobj: -4.2815474e-04 Ad: 9.34e-01 Dobj:  3.8633036e-03
+Iter:  7 Ap: 1.00e+00 Pobj: -4.3920196e-05 Ad: 9.88e-01 Dobj:  1.7392285e-04
+Iter:  8 Ap: 1.00e+00 Pobj: -2.3698636e-06 Ad: 9.99e-01 Dobj:  4.5447245e-06
+Iter:  9 Ap: 1.00e+00 Pobj: -9.4705116e-08 Ad: 1.00e+00 Dobj: -2.3966141e-06
+Iter: 10 Ap: 1.00e+00 Pobj: -4.0174413e-09 Ad: 9.69e-01 Dobj: -9.9538646e-08
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, ComplexF64}[(1.0 - 0.0im), (-0.5773502691896257 - 0.0im)x₃ + (-0.5773502691896257 - 0.0im)x₂ + (-0.5773502691896257 - 0.0im)x₁]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, ComplexF64}[(-0.577350269189626 - 0.0im)x₃ + (0.2886751345948128 + 0.5000000000000001im)x₂ + (0.28867513459481314 - 0.49999999999999994im)x₁]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, ComplexF64}[(-0.577350269189626 - 0.0im)x₃ + (0.28867513459481314 - 0.49999999999999994im)x₂ + (0.2886751345948128 + 0.5000000000000001im)x₁]

We can see that the real invariant subspace was in fact coming from two complex conjugate complex invariant subspaces:

complex_basis = basis[1] + im * basis[2]
+image = Symmetry.SymbolicWedderburn.action(action, g, complex_basis)

\[ (0.4082482904638631 - 0.7071067811865475im)x_{3} + (0.4082482904638631 + 0.7071067811865475im)x_{2} + (-0.8164965809277261 + 0.0im)x_{1} \]

And there is a direct correspondance between the representation of the real and complex versions:

(a + b * im) * complex_basis

\[ (0.4082482904638631 - 0.7071067811865476im)x_{3} + (0.4082482904638629 + 0.7071067811865475im)x_{2} + (-0.816496580927726 + 5.551115123125783e-17im)x_{1} \]


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Symmetry/dihedral.ipynb b/previews/PR347/generated/Symmetry/dihedral.ipynb new file mode 100644 index 000000000..800ee1cec --- /dev/null +++ b/previews/PR347/generated/Symmetry/dihedral.ipynb @@ -0,0 +1,372 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Dihedral symmetry of the Robinson form" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Example 5.4 of [GP04]\n", + "\n", + "[GP04] Gatermann, Karin and Parrilo, Pablo A.\n", + "*Symmetry groups, semidefinite programs, and sums of squares*.\n", + "Journal of Pure and Applied Algebra 192.1-3 (2004): 95-128." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "We start by defining the Dihedral group of order 8.\n", + "This group is isomorphic to the following permutation group:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Permutation group on 2 generators generated by\n (1,3)\n (1,2,3,4)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using PermutationGroups\n", + "d = perm\"(1, 2, 3, 4)\"\n", + "c = perm\"(1, 3)\"\n", + "G = PermGroup([c, d])" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We could rely on this isomorphism to define this group.\n", + "However, in order to illustrate how to do symmetry reduction with a custom group,\n", + "we show in this example what should be implemented to define a new group." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "import GroupsCore\n", + "\n", + "struct DihedralGroup <: GroupsCore.Group\n", + " n::Int\n", + "end\n", + "\n", + "struct DihedralElement <: GroupsCore.GroupElement\n", + " n::Int\n", + " reflection::Bool\n", + " id::Int\n", + "end" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "Implementing GroupsCore API:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "Base.one(G::DihedralGroup) = DihedralElement(G.n, false, 0)\n", + "\n", + "Base.eltype(::Type{DihedralGroup}) = DihedralElement\n", + "Base.IteratorSize(::Type{DihedralGroup}) = Base.HasLength()\n", + "\n", + "function Base.iterate(G::DihedralGroup, prev::DihedralElement=DihedralElement(G.n, false, -1))\n", + " if prev.id + 1 >= G.n\n", + " if prev.reflection\n", + " return nothing\n", + " else\n", + " next = DihedralElement(G.n, true, 0)\n", + " end\n", + " else\n", + " next = DihedralElement(G.n, prev.reflection, prev.id + 1)\n", + " end\n", + " return next, next\n", + "end\n", + "\n", + "GroupsCore.order(::Type{T}, G::DihedralGroup) where {T} = convert(T, 2G.n)\n", + "GroupsCore.gens(G::DihedralGroup) = [DihedralElement(G.n, false, 1), DihedralElement(G.n, true, 0)]" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Base.rand not needed for our purposes here" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "Base.parent(g::DihedralElement) = DihedralGroup(g.n)\n", + "function Base.:(==)(g::DihedralElement, h::DihedralElement)\n", + " return g.n == h.n && g.reflection == h.reflection && g.id == h.id\n", + "end\n", + "\n", + "function Base.inv(el::DihedralElement)\n", + " if el.reflection || iszero(el.id)\n", + " return el\n", + " else\n", + " return DihedralElement(el.n, false, el.n - el.id)\n", + " end\n", + "end\n", + "function Base.:*(a::DihedralElement, b::DihedralElement)\n", + " a.n == b.n || error(\"Cannot multiply elements from different Dihedral groups\")\n", + " id = mod(a.reflection ? a.id - b.id : a.id + b.id, a.n)\n", + " return DihedralElement(a.n, a.reflection != b.reflection, id)\n", + "end\n", + "\n", + "Base.copy(a::DihedralElement) = DihedralElement(a.n, a.reflection, a.id)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "optional functions:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "function GroupsCore.order(el::DihedralElement)\n", + " if el.reflection\n", + " return 2\n", + " else\n", + " if iszero(el.id)\n", + " return 1\n", + " else\n", + " return div(el.n, gcd(el.n, el.id))\n", + " end\n", + " end\n", + "end" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "The Robinson form is invariant under the following action of the Dihedral group on monomials:\n", + "The action of each element of the groups is to map the variables `x, y` to:\n", + "\n", + "| id | rotation | reflection |\n", + "|----|----------|------------|\n", + "| 0 | x, y | y, x |\n", + "| 1 | -y, x | -x, y |\n", + "| 2 | -x, -y | -y, -x |\n", + "| 3 | y, -x | x, -y |" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶", + "text/latex": "$$ 1 - y^{2} - x^{2} - y^{4} + 3x^{2}y^{2} - x^{4} + y^{6} - x^{2}y^{4} - x^{4}y^{2} + x^{6} $$" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "using DynamicPolynomials\n", + "@polyvar x y\n", + "struct DihedralAction <: Symmetry.OnMonomials end\n", + "import SymbolicWedderburn\n", + "SymbolicWedderburn.coeff_type(::DihedralAction) = Float64\n", + "function SymbolicWedderburn.action(::DihedralAction, el::DihedralElement, mono::AbstractMonomial)\n", + " if iseven(el.reflection + el.id)\n", + " var_x, var_y = x, y\n", + " else\n", + " var_x, var_y = y, x\n", + " end\n", + " sign_x = 1 <= el.id <= 2 ? -1 : 1\n", + " sign_y = 2 <= el.id ? -1 : 1\n", + " return mono([x, y] => [sign_x * var_x, sign_y * var_y])\n", + "end\n", + "\n", + "poly = x^6 + y^6 - x^4 * y^2 - y^4 * x^2 - x^4 - y^4 - x^2 - y^2 + 3x^2 * y^2 + 1" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We can verify that `poly` is indeed invariant under the action of each element of the group as follows." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n", + "SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶\n" + ] + } + ], + "cell_type": "code", + "source": [ + "G = DihedralGroup(4)\n", + "for g in G\n", + " @show SymbolicWedderburn.action(DihedralAction(), g, poly)\n", + "end" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "We can exploit this symmetry for reducing the problem using the `SymmetricIdeal` certificate as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 11 Ap: 9.58e-01 Pobj: -1.6774514e-10 Ad: 9.58e-01 Dobj: -4.5554076e-09 \n", + "Success: SDP solved\n", + "Primal objective value: -1.6774514e-10 \n", + "Dual objective value: -4.5554076e-09 \n", + "Relative primal infeasibility: 1.10e-14 \n", + "Relative dual infeasibility: 1.18e-09 \n", + "Real Relative Gap: -4.39e-09 \n", + "XZ Relative Gap: 1.22e-09 \n", + "DIMACS error measures: 1.89e-14 0.00e+00 2.82e-09 0.00e+00 -4.39e-09 1.22e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 7.31e-01 Pobj: -5.9540730e+00 Ad: 8.42e-01 Dobj: 3.0671681e-01 \n", + "Iter: 2 Ap: 8.67e-01 Pobj: -1.6845198e+01 Ad: 8.68e-01 Dobj: 7.9208056e+00 \n", + "Iter: 3 Ap: 8.41e-01 Pobj: -6.5167134e+00 Ad: 6.91e-01 Dobj: 4.6340995e+00 \n", + "Iter: 4 Ap: 7.89e-01 Pobj: -3.0718725e+00 Ad: 8.67e-01 Dobj: 8.7844427e-01 \n", + "Iter: 5 Ap: 8.59e-01 Pobj: -1.8420731e+00 Ad: 8.47e-01 Dobj: -3.3091073e-01 \n", + "Iter: 6 Ap: 7.40e-01 Pobj: -1.2180543e+00 Ad: 8.00e-01 Dobj: -6.8726801e-01 \n", + "Iter: 7 Ap: 8.82e-01 Pobj: -1.0523759e+00 Ad: 6.48e-01 Dobj: -8.1732010e-01 \n", + "Iter: 8 Ap: 6.75e-01 Pobj: -9.8406190e-01 Ad: 7.70e-01 Dobj: -8.8525802e-01 \n", + "Iter: 9 Ap: 8.70e-01 Pobj: -9.5552035e-01 Ad: 7.26e-01 Dobj: -9.1517421e-01 \n", + "Iter: 10 Ap: 1.00e+00 Pobj: -9.2933412e-01 Ad: 8.92e-01 Dobj: -9.2629286e-01 \n", + "Iter: 11 Ap: 8.61e-01 Pobj: -9.2914325e-01 Ad: 9.11e-01 Dobj: -9.3036068e-01 \n", + "Iter: 12 Ap: 1.00e+00 Pobj: -9.2898054e-01 Ad: 1.00e+00 Dobj: -9.3115787e-01 \n", + "Iter: 13 Ap: 7.19e-01 Pobj: -9.2961473e-01 Ad: 5.76e-01 Dobj: -9.3155210e-01 \n", + "Iter: 14 Ap: 1.00e+00 Pobj: -9.2967228e-01 Ad: 3.55e-01 Dobj: -9.3180771e-01 \n", + "Iter: 15 Ap: 4.26e-01 Pobj: -9.3065963e-01 Ad: 1.00e+00 Dobj: -9.3175040e-01 \n", + "Iter: 16 Ap: 1.00e+00 Pobj: -9.3042297e-01 Ad: 1.00e+00 Dobj: -9.3211446e-01 \n", + "Iter: 17 Ap: 5.06e-01 Pobj: -9.3106101e-01 Ad: 6.25e-01 Dobj: -9.3240546e-01 \n", + "Iter: 18 Ap: 7.18e-01 Pobj: -9.3146998e-01 Ad: 4.44e-01 Dobj: -9.3257853e-01 \n", + "Iter: 19 Ap: 1.00e+00 Pobj: -9.3128112e-01 Ad: 3.48e-01 Dobj: -9.3271014e-01 \n", + "Iter: 20 Ap: 4.85e-01 Pobj: -9.3206037e-01 Ad: 1.00e+00 Dobj: -9.3257740e-01 \n", + "Iter: 21 Ap: 1.00e+00 Pobj: -9.3178232e-01 Ad: 1.00e+00 Dobj: -9.3276737e-01 \n", + "Iter: 22 Ap: 7.26e-01 Pobj: -9.3197870e-01 Ad: 7.39e-01 Dobj: -9.3290369e-01 \n", + "Iter: 23 Ap: 4.04e-01 Pobj: -9.3208730e-01 Ad: 4.06e-01 Dobj: -9.3295435e-01 \n", + "Iter: 24 Ap: 1.00e+00 Pobj: -9.3209505e-01 Ad: 1.00e+00 Dobj: -9.3296372e-01 \n", + "Iter: 25 Ap: 7.03e-01 Pobj: -9.3212572e-01 Ad: 7.08e-01 Dobj: -9.3298098e-01 \n", + "Iter: 26 Ap: 9.98e-01 Pobj: -9.3212657e-01 Ad: 9.95e-01 Dobj: -9.3298156e-01 \n", + "value(t) = -0.9321266534577521\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[y³, x²y, y]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-x³, -xy², -x]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[1.0, -0.7071067811865472y² - 0.7071067811865475x²]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[xy]\n", + "DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-0.7071067811865472y² + 0.7071067811865475x²]\n" + ] + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "function solve(G)\n", + " solver = CSDP.Optimizer\n", + " model = Model(solver)\n", + " @variable(model, t)\n", + " @objective(model, Max, t)\n", + " pattern = Symmetry.Pattern(G, DihedralAction())\n", + " con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\n", + " optimize!(model)\n", + " @show value(t)\n", + "\n", + "\n", + " for g in gram_matrix(con_ref).blocks\n", + " println(g.basis.polynomials)\n", + " end\n", + "end\n", + "solve(G)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "We notice that we indeed find `-3825/4096` and that symmetry was exploited." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Symmetry/dihedral.jl b/previews/PR347/generated/Symmetry/dihedral.jl new file mode 100644 index 000000000..fceef11d5 --- /dev/null +++ b/previews/PR347/generated/Symmetry/dihedral.jl @@ -0,0 +1,113 @@ +using PermutationGroups +d = perm"(1, 2, 3, 4)" +c = perm"(1, 3)" +G = PermGroup([c, d]) + +import GroupsCore + +struct DihedralGroup <: GroupsCore.Group + n::Int +end + +struct DihedralElement <: GroupsCore.GroupElement + n::Int + reflection::Bool + id::Int +end + +Base.one(G::DihedralGroup) = DihedralElement(G.n, false, 0) + +Base.eltype(::Type{DihedralGroup}) = DihedralElement +Base.IteratorSize(::Type{DihedralGroup}) = Base.HasLength() + +function Base.iterate(G::DihedralGroup, prev::DihedralElement=DihedralElement(G.n, false, -1)) + if prev.id + 1 >= G.n + if prev.reflection + return nothing + else + next = DihedralElement(G.n, true, 0) + end + else + next = DihedralElement(G.n, prev.reflection, prev.id + 1) + end + return next, next +end + +GroupsCore.order(::Type{T}, G::DihedralGroup) where {T} = convert(T, 2G.n) +GroupsCore.gens(G::DihedralGroup) = [DihedralElement(G.n, false, 1), DihedralElement(G.n, true, 0)] + +Base.parent(g::DihedralElement) = DihedralGroup(g.n) +function Base.:(==)(g::DihedralElement, h::DihedralElement) + return g.n == h.n && g.reflection == h.reflection && g.id == h.id +end + +function Base.inv(el::DihedralElement) + if el.reflection || iszero(el.id) + return el + else + return DihedralElement(el.n, false, el.n - el.id) + end +end +function Base.:*(a::DihedralElement, b::DihedralElement) + a.n == b.n || error("Cannot multiply elements from different Dihedral groups") + id = mod(a.reflection ? a.id - b.id : a.id + b.id, a.n) + return DihedralElement(a.n, a.reflection != b.reflection, id) +end + +Base.copy(a::DihedralElement) = DihedralElement(a.n, a.reflection, a.id) + +function GroupsCore.order(el::DihedralElement) + if el.reflection + return 2 + else + if iszero(el.id) + return 1 + else + return div(el.n, gcd(el.n, el.id)) + end + end +end + +using SumOfSquares +using DynamicPolynomials +@polyvar x y +struct DihedralAction <: Symmetry.OnMonomials end +import SymbolicWedderburn +SymbolicWedderburn.coeff_type(::DihedralAction) = Float64 +function SymbolicWedderburn.action(::DihedralAction, el::DihedralElement, mono::AbstractMonomial) + if iseven(el.reflection + el.id) + var_x, var_y = x, y + else + var_x, var_y = y, x + end + sign_x = 1 <= el.id <= 2 ? -1 : 1 + sign_y = 2 <= el.id ? -1 : 1 + return mono([x, y] => [sign_x * var_x, sign_y * var_y]) +end + +poly = x^6 + y^6 - x^4 * y^2 - y^4 * x^2 - x^4 - y^4 - x^2 - y^2 + 3x^2 * y^2 + 1 + +G = DihedralGroup(4) +for g in G + @show SymbolicWedderburn.action(DihedralAction(), g, poly) +end + +import CSDP +function solve(G) + solver = CSDP.Optimizer + model = Model(solver) + @variable(model, t) + @objective(model, Max, t) + pattern = Symmetry.Pattern(G, DihedralAction()) + con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) + optimize!(model) + @show value(t) + + + for g in gram_matrix(con_ref).blocks + println(g.basis.polynomials) + end +end +solve(G) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Symmetry/dihedral/index.html b/previews/PR347/generated/Symmetry/dihedral/index.html new file mode 100644 index 000000000..cbef6205f --- /dev/null +++ b/previews/PR347/generated/Symmetry/dihedral/index.html @@ -0,0 +1,149 @@ + +Dihedral symmetry of the Robinson form · SumOfSquares

Dihedral symmetry of the Robinson form

Adapted from: Example 5.4 of [GP04]

[GP04] Gatermann, Karin and Parrilo, Pablo A. Symmetry groups, semidefinite programs, and sums of squares. Journal of Pure and Applied Algebra 192.1-3 (2004): 95-128.

We start by defining the Dihedral group of order 8. This group is isomorphic to the following permutation group:

using PermutationGroups
+d = perm"(1, 2, 3, 4)"
+c = perm"(1, 3)"
+G = PermGroup([c, d])
Permutation group on 2 generators generated by
+ (1,3)
+ (1,2,3,4)

We could rely on this isomorphism to define this group. However, in order to illustrate how to do symmetry reduction with a custom group, we show in this example what should be implemented to define a new group.

import GroupsCore
+
+struct DihedralGroup <: GroupsCore.Group
+    n::Int
+end
+
+struct DihedralElement <: GroupsCore.GroupElement
+    n::Int
+    reflection::Bool
+    id::Int
+end

Implementing GroupsCore API:

Base.one(G::DihedralGroup) = DihedralElement(G.n, false, 0)
+
+Base.eltype(::Type{DihedralGroup}) = DihedralElement
+Base.IteratorSize(::Type{DihedralGroup}) = Base.HasLength()
+
+function Base.iterate(G::DihedralGroup, prev::DihedralElement=DihedralElement(G.n, false, -1))
+    if prev.id + 1 >= G.n
+        if prev.reflection
+            return nothing
+        else
+            next = DihedralElement(G.n, true, 0)
+        end
+    else
+        next = DihedralElement(G.n, prev.reflection, prev.id + 1)
+    end
+    return next, next
+end
+
+GroupsCore.order(::Type{T}, G::DihedralGroup) where {T} = convert(T, 2G.n)
+GroupsCore.gens(G::DihedralGroup) = [DihedralElement(G.n, false, 1), DihedralElement(G.n, true, 0)]

Base.rand not needed for our purposes here

Base.parent(g::DihedralElement) = DihedralGroup(g.n)
+function Base.:(==)(g::DihedralElement, h::DihedralElement)
+    return g.n == h.n && g.reflection == h.reflection && g.id == h.id
+end
+
+function Base.inv(el::DihedralElement)
+    if el.reflection || iszero(el.id)
+        return el
+    else
+        return DihedralElement(el.n, false, el.n - el.id)
+    end
+end
+function Base.:*(a::DihedralElement, b::DihedralElement)
+    a.n == b.n || error("Cannot multiply elements from different Dihedral groups")
+    id = mod(a.reflection ? a.id - b.id : a.id + b.id, a.n)
+    return DihedralElement(a.n, a.reflection != b.reflection, id)
+end
+
+Base.copy(a::DihedralElement) = DihedralElement(a.n, a.reflection, a.id)

optional functions:

function GroupsCore.order(el::DihedralElement)
+    if el.reflection
+        return 2
+    else
+        if iszero(el.id)
+            return 1
+        else
+            return div(el.n, gcd(el.n, el.id))
+        end
+    end
+end

The Robinson form is invariant under the following action of the Dihedral group on monomials: The action of each element of the groups is to map the variables x, y to:

idrotationreflection
0x, yy, x
1-y, x-x, y
2-x, -y-y, -x
3y, -xx, -y
using SumOfSquares
+using DynamicPolynomials
+@polyvar x y
+struct DihedralAction <: Symmetry.OnMonomials end
+import SymbolicWedderburn
+SymbolicWedderburn.coeff_type(::DihedralAction) = Float64
+function SymbolicWedderburn.action(::DihedralAction, el::DihedralElement, mono::AbstractMonomial)
+    if iseven(el.reflection + el.id)
+        var_x, var_y = x, y
+    else
+        var_x, var_y = y, x
+    end
+    sign_x = 1 <= el.id <= 2 ? -1 : 1
+    sign_y = 2 <= el.id ? -1 : 1
+    return mono([x, y] => [sign_x * var_x, sign_y * var_y])
+end
+
+poly = x^6 + y^6 - x^4 * y^2 - y^4 * x^2 - x^4 - y^4 - x^2 - y^2 + 3x^2 * y^2 + 1

\[ 1 - y^{2} - x^{2} - y^{4} + 3x^{2}y^{2} - x^{4} + y^{6} - x^{2}y^{4} - x^{4}y^{2} + x^{6} \]

We can verify that poly is indeed invariant under the action of each element of the group as follows.

G = DihedralGroup(4)
+for g in G
+    @show SymbolicWedderburn.action(DihedralAction(), g, poly)
+end
SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶
+SymbolicWedderburn.action(DihedralAction(), g, poly) = 1 - y² - x² - y⁴ + 3x²y² - x⁴ + y⁶ - x²y⁴ - x⁴y² + x⁶

We can exploit this symmetry for reducing the problem using the SymmetricIdeal certificate as follows:

import CSDP
+function solve(G)
+    solver = CSDP.Optimizer
+    model = Model(solver)
+    @variable(model, t)
+    @objective(model, Max, t)
+    pattern = Symmetry.Pattern(G, DihedralAction())
+    con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)
+    optimize!(model)
+    @show value(t)
+
+
+    for g in gram_matrix(con_ref).blocks
+        println(g.basis.polynomials)
+    end
+end
+solve(G)
Iter: 11 Ap: 9.58e-01 Pobj: -1.6774514e-10 Ad: 9.58e-01 Dobj: -4.5554076e-09
+Success: SDP solved
+Primal objective value: -1.6774514e-10
+Dual objective value: -4.5554076e-09
+Relative primal infeasibility: 1.10e-14
+Relative dual infeasibility: 1.18e-09
+Real Relative Gap: -4.39e-09
+XZ Relative Gap: 1.22e-09
+DIMACS error measures: 1.89e-14 0.00e+00 2.82e-09 0.00e+00 -4.39e-09 1.22e-09
+CSDP 6.2.0
+Iter:  0 Ap: 0.00e+00 Pobj:  0.0000000e+00 Ad: 0.00e+00 Dobj:  0.0000000e+00
+Iter:  1 Ap: 7.31e-01 Pobj: -5.9540730e+00 Ad: 8.42e-01 Dobj:  3.0671681e-01
+Iter:  2 Ap: 8.67e-01 Pobj: -1.6845198e+01 Ad: 8.68e-01 Dobj:  7.9208056e+00
+Iter:  3 Ap: 8.41e-01 Pobj: -6.5167134e+00 Ad: 6.91e-01 Dobj:  4.6340995e+00
+Iter:  4 Ap: 7.89e-01 Pobj: -3.0718725e+00 Ad: 8.67e-01 Dobj:  8.7844427e-01
+Iter:  5 Ap: 8.59e-01 Pobj: -1.8420731e+00 Ad: 8.47e-01 Dobj: -3.3091073e-01
+Iter:  6 Ap: 7.40e-01 Pobj: -1.2180543e+00 Ad: 8.00e-01 Dobj: -6.8726801e-01
+Iter:  7 Ap: 8.82e-01 Pobj: -1.0523759e+00 Ad: 6.48e-01 Dobj: -8.1732010e-01
+Iter:  8 Ap: 6.75e-01 Pobj: -9.8406190e-01 Ad: 7.70e-01 Dobj: -8.8525802e-01
+Iter:  9 Ap: 8.70e-01 Pobj: -9.5552035e-01 Ad: 7.26e-01 Dobj: -9.1517421e-01
+Iter: 10 Ap: 1.00e+00 Pobj: -9.2933412e-01 Ad: 8.92e-01 Dobj: -9.2629286e-01
+Iter: 11 Ap: 8.61e-01 Pobj: -9.2914325e-01 Ad: 9.11e-01 Dobj: -9.3036068e-01
+Iter: 12 Ap: 1.00e+00 Pobj: -9.2898054e-01 Ad: 1.00e+00 Dobj: -9.3115787e-01
+Iter: 13 Ap: 7.19e-01 Pobj: -9.2961473e-01 Ad: 5.76e-01 Dobj: -9.3155210e-01
+Iter: 14 Ap: 1.00e+00 Pobj: -9.2967228e-01 Ad: 3.55e-01 Dobj: -9.3180771e-01
+Iter: 15 Ap: 4.26e-01 Pobj: -9.3065963e-01 Ad: 1.00e+00 Dobj: -9.3175040e-01
+Iter: 16 Ap: 1.00e+00 Pobj: -9.3042297e-01 Ad: 1.00e+00 Dobj: -9.3211446e-01
+Iter: 17 Ap: 5.06e-01 Pobj: -9.3106101e-01 Ad: 6.25e-01 Dobj: -9.3240546e-01
+Iter: 18 Ap: 7.18e-01 Pobj: -9.3146998e-01 Ad: 4.44e-01 Dobj: -9.3257853e-01
+Iter: 19 Ap: 1.00e+00 Pobj: -9.3128112e-01 Ad: 3.48e-01 Dobj: -9.3271014e-01
+Iter: 20 Ap: 4.85e-01 Pobj: -9.3206037e-01 Ad: 1.00e+00 Dobj: -9.3257740e-01
+Iter: 21 Ap: 1.00e+00 Pobj: -9.3178232e-01 Ad: 1.00e+00 Dobj: -9.3276737e-01
+Iter: 22 Ap: 7.26e-01 Pobj: -9.3197870e-01 Ad: 7.39e-01 Dobj: -9.3290369e-01
+Iter: 23 Ap: 4.04e-01 Pobj: -9.3208730e-01 Ad: 4.06e-01 Dobj: -9.3295435e-01
+Iter: 24 Ap: 1.00e+00 Pobj: -9.3209505e-01 Ad: 1.00e+00 Dobj: -9.3296372e-01
+Iter: 25 Ap: 7.03e-01 Pobj: -9.3212572e-01 Ad: 7.08e-01 Dobj: -9.3298098e-01
+Iter: 26 Ap: 9.98e-01 Pobj: -9.3212657e-01 Ad: 9.95e-01 Dobj: -9.3298156e-01
+value(t) = -0.9321266534577521
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[y³, x²y, y]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-x³, -xy², -x]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[1.0, -0.7071067811865472y² - 0.7071067811865475x²]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[xy]
+DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}[-0.7071067811865472y² + 0.7071067811865475x²]

We notice that we indeed find -3825/4096 and that symmetry was exploited.


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Symmetry/even_reduction.ipynb b/previews/PR347/generated/Symmetry/even_reduction.ipynb new file mode 100644 index 000000000..a3686fae7 --- /dev/null +++ b/previews/PR347/generated/Symmetry/even_reduction.ipynb @@ -0,0 +1,193 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Even reduction" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(x,)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We would like to find the minimum value of the following polynomial:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "poly = x^4 - 2x^2\n", + "\n", + "using SumOfSquares" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We define the custom action as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Permutation group on 1 generator generated by\n (1,2)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "struct OnSign <: Symmetry.OnMonomials end\n", + "using PermutationGroups\n", + "import SymbolicWedderburn\n", + "SymbolicWedderburn.coeff_type(::OnSign) = Float64\n", + "function SymbolicWedderburn.action(::OnSign, p::Permutation, mono::AbstractMonomial)\n", + " if isone(p) || iseven(DynamicPolynomials.degree(mono))\n", + " return 1 * mono\n", + " else\n", + " @assert p.perm == perm\"(1,2)\"\n", + " return -1 * mono\n", + " end\n", + "end\n", + "G = PermGroup([perm\"(1,2)\"])" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We can exploit the symmetry as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Stuck at edge of primal feasibility, giving up. \n", + "Partial Success: SDP solved with reduced accuracy\n", + "Primal objective value: -9.3212665e-01 \n", + "Dual objective value: -9.3298157e-01 \n", + "Relative primal infeasibility: 3.98e-08 \n", + "Relative dual infeasibility: 3.29e-10 \n", + "Real Relative Gap: -2.98e-04 \n", + "XZ Relative Gap: 2.05e-09 \n", + "DIMACS error measures: 5.22e-08 0.00e+00 8.68e-10 0.00e+00 -2.98e-04 2.05e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 1.00e+00 Pobj: -7.7333326e+00 Ad: 9.00e-01 Dobj: 5.2199992e+00 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: -4.7469915e+00 Ad: 9.00e-01 Dobj: 4.9208659e-01 \n", + "Iter: 3 Ap: 1.00e+00 Pobj: -1.3207096e+00 Ad: 9.00e-01 Dobj: -8.2374194e-01 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -1.0090262e+00 Ad: 9.00e-01 Dobj: -9.8744356e-01 \n", + "Iter: 5 Ap: 9.00e-01 Pobj: -1.0008968e+00 Ad: 1.00e+00 Dobj: -9.9998051e-01 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -1.0001857e+00 Ad: 1.00e+00 Dobj: -9.9990815e-01 \n", + "Iter: 7 Ap: 9.00e-01 Pobj: -1.0000185e+00 Ad: 1.00e+00 Dobj: -1.0000019e+00 \n", + "Iter: 8 Ap: 1.00e+00 Pobj: -1.0000015e+00 Ad: 1.00e+00 Dobj: -1.0000013e+00 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -1.0000001e+00 Ad: 1.00e+00 Dobj: -1.0000000e+00 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-1.000000007084374" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = CSDP.Optimizer\n", + "model = Model(solver)\n", + "@variable(model, t)\n", + "@objective(model, Max, t)\n", + "pattern = Symmetry.Pattern(G, OnSign())\n", + "con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\n", + "optimize!(model)\n", + "value(t)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We indeed find `-1`, let's verify that symmetry was exploited:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "BlockDiagonalGramMatrix with 2 blocks:\n[1] Block with row/column basis:\n FixedPolynomialBasis([1.0, x^2])\n And entries in a 2×2 SymMatrix{Float64}:\n 1.0000000070844732 -1.0000000020056958\n -1.0000000020056958 1.0000000000000828\n[2] Block with row/column basis:\n FixedPolynomialBasis([x])\n And entries in a 1×1 SymMatrix{Float64}:\n 4.011410529947057e-9" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "gram_matrix(con_ref)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Symmetry/even_reduction.jl b/previews/PR347/generated/Symmetry/even_reduction.jl new file mode 100644 index 000000000..a7977009a --- /dev/null +++ b/previews/PR347/generated/Symmetry/even_reduction.jl @@ -0,0 +1,34 @@ +using DynamicPolynomials +@polyvar x + +poly = x^4 - 2x^2 + +using SumOfSquares + +struct OnSign <: Symmetry.OnMonomials end +using PermutationGroups +import SymbolicWedderburn +SymbolicWedderburn.coeff_type(::OnSign) = Float64 +function SymbolicWedderburn.action(::OnSign, p::Permutation, mono::AbstractMonomial) + if isone(p) || iseven(DynamicPolynomials.degree(mono)) + return 1 * mono + else + @assert p.perm == perm"(1,2)" + return -1 * mono + end +end +G = PermGroup([perm"(1,2)"]) + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, OnSign()) +con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) +optimize!(model) +value(t) + +gram_matrix(con_ref) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Symmetry/even_reduction/index.html b/previews/PR347/generated/Symmetry/even_reduction/index.html new file mode 100644 index 000000000..745514622 --- /dev/null +++ b/previews/PR347/generated/Symmetry/even_reduction/index.html @@ -0,0 +1,35 @@ + +Even reduction · SumOfSquares

Even reduction

using DynamicPolynomials
+@polyvar x
(x,)

We would like to find the minimum value of the following polynomial:

poly = x^4 - 2x^2
+
+using SumOfSquares

We define the custom action as follows:

struct OnSign <: Symmetry.OnMonomials end
+using PermutationGroups
+import SymbolicWedderburn
+SymbolicWedderburn.coeff_type(::OnSign) = Float64
+function SymbolicWedderburn.action(::OnSign, p::Permutation, mono::AbstractMonomial)
+    if isone(p) || iseven(DynamicPolynomials.degree(mono))
+        return 1 * mono
+    else
+        @assert p.perm == perm"(1,2)"
+        return -1 * mono
+    end
+end
+G = PermGroup([perm"(1,2)"])
Permutation group on 1 generator generated by
+ (1,2)

We can exploit the symmetry as follows:

import CSDP
+solver = CSDP.Optimizer
+model = Model(solver)
+@variable(model, t)
+@objective(model, Max, t)
+pattern = Symmetry.Pattern(G, OnSign())
+con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)
+optimize!(model)
+value(t)
-1.000000007084374

We indeed find -1, let's verify that symmetry was exploited:

gram_matrix(con_ref)
BlockDiagonalGramMatrix with 2 blocks:
+[1] Block with row/column basis:
+     FixedPolynomialBasis([1.0, x^2])
+    And entries in a 2×2 SymMatrix{Float64}:
+      1.0000000070844732  -1.0000000020056958
+     -1.0000000020056958   1.0000000000000828
+[2] Block with row/column basis:
+     FixedPolynomialBasis([x])
+    And entries in a 1×1 SymMatrix{Float64}:
+     4.011410529947057e-9

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Symmetry/permutation_symmetry.ipynb b/previews/PR347/generated/Symmetry/permutation_symmetry.ipynb new file mode 100644 index 000000000..29d6c4254 --- /dev/null +++ b/previews/PR347/generated/Symmetry/permutation_symmetry.ipynb @@ -0,0 +1,222 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Symmetry reduction" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: [SymbolicWedderburn example](https://github.com/kalmarek/SymbolicWedderburn.jl/blob/tw/ex_sos/examples/ex_C4.jl)" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃, x₄],)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "import MutableArithmetics as MA\n", + "using MultivariatePolynomials\n", + "using MultivariateBases\n", + "\n", + "using DynamicPolynomials\n", + "@polyvar x[1:4]" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We would like to find the minimum value of the polynomial" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "x₄ + x₃ + x₂ + x₁ + x₄² + x₃² + x₂² + x₁²", + "text/latex": "$$ x_{4} + x_{3} + x_{2} + x_{1} + x_{4}^{2} + x_{3}^{2} + x_{2}^{2} + x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "poly = sum(x) + sum(x.^2)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "As we can decouple the problem for each `x[i]` for which `x[i] + x[i]^2` has\n", + "minimum value 0.25, we would expect to get `-1` as answer.\n", + "Can this decoupling be exploited by SumOfSquares as well ?\n", + "For this, we need to use a certificate that can exploit the permutation symmetry of the polynomial." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We define the symmetry group as a permutation group in the variables.\n", + "In order to do that, we define the action of a permutation on a monomial\n", + "as the monomial obtained after permuting the variables." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "Permutation group on 1 generator generated by\n (1,2,3,4)" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "using PermutationGroups\n", + "G = PermGroup([perm\"(1,2,3,4)\"])" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We can use this certificate as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iter: 10 Ap: 9.00e-01 Pobj: -1.0000000e+00 Ad: 1.00e+00 Dobj: -1.0000000e+00 \n", + "Success: SDP solved\n", + "Primal objective value: -1.0000000e+00 \n", + "Dual objective value: -1.0000000e+00 \n", + "Relative primal infeasibility: 4.04e-14 \n", + "Relative dual infeasibility: 2.78e-10 \n", + "Real Relative Gap: 2.16e-09 \n", + "XZ Relative Gap: 2.71e-09 \n", + "DIMACS error measures: 4.35e-14 0.00e+00 5.75e-10 0.00e+00 2.16e-09 2.71e-09\n", + "CSDP 6.2.0\n", + "Iter: 0 Ap: 0.00e+00 Pobj: 0.0000000e+00 Ad: 0.00e+00 Dobj: 0.0000000e+00 \n", + "Iter: 1 Ap: 1.00e+00 Pobj: -6.9333327e+00 Ad: 9.27e-01 Dobj: 2.5022292e+01 \n", + "Iter: 2 Ap: 1.00e+00 Pobj: -3.3371292e+00 Ad: 9.16e-01 Dobj: 4.2284146e+00 \n", + "Iter: 3 Ap: 1.00e+00 Pobj: -1.1686719e+00 Ad: 8.76e-01 Dobj: 1.7691868e-01 \n", + "Iter: 4 Ap: 1.00e+00 Pobj: -1.0108916e+00 Ad: 9.30e-01 Dobj: -8.8720183e-01 \n", + "Iter: 5 Ap: 1.00e+00 Pobj: -1.0008407e+00 Ad: 9.56e-01 Dobj: -9.9267833e-01 \n", + "Iter: 6 Ap: 1.00e+00 Pobj: -1.0000536e+00 Ad: 9.78e-01 Dobj: -9.9968404e-01 \n", + "Iter: 7 Ap: 1.00e+00 Pobj: -1.0000039e+00 Ad: 1.00e+00 Dobj: -9.9999122e-01 \n", + "Iter: 8 Ap: 1.00e+00 Pobj: -1.0000004e+00 Ad: 1.00e+00 Dobj: -1.0000010e+00 \n", + "Iter: 9 Ap: 1.00e+00 Pobj: -1.0000000e+00 Ad: 9.88e-01 Dobj: -1.0000000e+00 \n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "-1.0000000005215735" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = CSDP.Optimizer\n", + "model = Model(solver)\n", + "@variable(model, t)\n", + "@objective(model, Max, t)\n", + "pattern = Symmetry.Pattern(G, Symmetry.VariablePermutation())\n", + "con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\n", + "optimize!(model)\n", + "value(t)" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We indeed find `-1`, let's verify that symmetry was exploited:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "4-element Vector{GramMatrix{Float64, FixedPolynomialBasis{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}, Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}}, Float64, SymMatrix{Float64}}}:\n GramMatrix with row/column basis:\n FixedPolynomialBasis([1.0, -0.5*x[4] - 0.5*x[3] - 0.5*x[2] - 0.5*x[1]])\nAnd entries in a 2×2 SymMatrix{Float64}:\n 1.0000000005215735 -1.0000000000000018\n -1.0000000000000018 0.9999999999999988\n GramMatrix with row/column basis:\n FixedPolynomialBasis([-0.7071067811865472*x[4] + 0.7071067811865475*x[2]])\nAnd entries in a 1×1 SymMatrix{Float64}:\n 0.9999999999999998\n GramMatrix with row/column basis:\n FixedPolynomialBasis([-0.7071067811865472*x[3] + 0.7071067811865475*x[1]])\nAnd entries in a 1×1 SymMatrix{Float64}:\n 0.9999999999999998\n GramMatrix with row/column basis:\n FixedPolynomialBasis([-0.5*x[4] + 0.5*x[3] - 0.5*x[2] + 0.5*x[1]])\nAnd entries in a 1×1 SymMatrix{Float64}:\n 0.9999999999999998" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "gram_matrix(con_ref).blocks" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Symmetry/permutation_symmetry.jl b/previews/PR347/generated/Symmetry/permutation_symmetry.jl new file mode 100644 index 000000000..945cd80dd --- /dev/null +++ b/previews/PR347/generated/Symmetry/permutation_symmetry.jl @@ -0,0 +1,27 @@ +import MutableArithmetics as MA +using MultivariatePolynomials +using MultivariateBases + +using DynamicPolynomials +@polyvar x[1:4] + +poly = sum(x) + sum(x.^2) + +using SumOfSquares + +using PermutationGroups +G = PermGroup([perm"(1,2,3,4)"]) + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, Symmetry.VariablePermutation()) +con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) +optimize!(model) +value(t) + +gram_matrix(con_ref).blocks + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Symmetry/permutation_symmetry/index.html b/previews/PR347/generated/Symmetry/permutation_symmetry/index.html new file mode 100644 index 000000000..042dc119d --- /dev/null +++ b/previews/PR347/generated/Symmetry/permutation_symmetry/index.html @@ -0,0 +1,34 @@ + +Symmetry reduction · SumOfSquares

Symmetry reduction

Adapted from: SymbolicWedderburn example

import MutableArithmetics as MA
+using MultivariatePolynomials
+using MultivariateBases
+
+using DynamicPolynomials
+@polyvar x[1:4]
(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃, x₄],)

We would like to find the minimum value of the polynomial

poly = sum(x) + sum(x.^2)

\[ x_{4} + x_{3} + x_{2} + x_{1} + x_{4}^{2} + x_{3}^{2} + x_{2}^{2} + x_{1}^{2} \]

As we can decouple the problem for each x[i] for which x[i] + x[i]^2 has minimum value 0.25, we would expect to get -1 as answer. Can this decoupling be exploited by SumOfSquares as well ? For this, we need to use a certificate that can exploit the permutation symmetry of the polynomial.

using SumOfSquares

We define the symmetry group as a permutation group in the variables. In order to do that, we define the action of a permutation on a monomial as the monomial obtained after permuting the variables.

using PermutationGroups
+G = PermGroup([perm"(1,2,3,4)"])
Permutation group on 1 generator generated by
+ (1,2,3,4)

We can use this certificate as follows:

import CSDP
+solver = CSDP.Optimizer
+model = Model(solver)
+@variable(model, t)
+@objective(model, Max, t)
+pattern = Symmetry.Pattern(G, Symmetry.VariablePermutation())
+con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)
+optimize!(model)
+value(t)
-1.0000000005215735

We indeed find -1, let's verify that symmetry was exploited:

gram_matrix(con_ref).blocks
4-element Vector{GramMatrix{Float64, FixedPolynomialBasis{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}, Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}}, Float64, SymMatrix{Float64}}}:
+ GramMatrix with row/column basis:
+ FixedPolynomialBasis([1.0, -0.5*x[4] - 0.5*x[3] - 0.5*x[2] - 0.5*x[1]])
+And entries in a 2×2 SymMatrix{Float64}:
+  1.0000000005215735  -1.0000000000000018
+ -1.0000000000000018   0.9999999999999988
+ GramMatrix with row/column basis:
+ FixedPolynomialBasis([-0.7071067811865472*x[4] + 0.7071067811865475*x[2]])
+And entries in a 1×1 SymMatrix{Float64}:
+ 0.9999999999999998
+ GramMatrix with row/column basis:
+ FixedPolynomialBasis([-0.7071067811865472*x[3] + 0.7071067811865475*x[1]])
+And entries in a 1×1 SymMatrix{Float64}:
+ 0.9999999999999998
+ GramMatrix with row/column basis:
+ FixedPolynomialBasis([-0.5*x[4] + 0.5*x[3] - 0.5*x[2] + 0.5*x[1]])
+And entries in a 1×1 SymMatrix{Float64}:
+ 0.9999999999999998

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Systems and Control/barrier_certificate.ipynb b/previews/PR347/generated/Systems and Control/barrier_certificate.ipynb new file mode 100644 index 000000000..1d07213a6 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/barrier_certificate.ipynb @@ -0,0 +1,3175 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Barrier certificates for collision avoidance" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Example 2 of \"Engineering applications of SOS polynomials\" by Georgina Hall, from\n", + "the 2019 AMS Short Course on Sum of Squares: Theory and Applications\n", + "Implementation by: Hugo Tadashi Kussaba" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:2]\n", + "\n", + "using SumOfSquares\n", + "using CSDP" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = SOSModel(solver);" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We define below the vector field $\\text{d}x/\\text{d}t = f$" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:\n x₂\n -x₂ - x₁ + 0.3333333333333333x₁³" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "f = [ x[2],\n", + " -x[1] + (1/3)*x[1]^3 - x[2]]" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "Semi-algebraic function describing the unsafe set 𝒳ᵤ" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "-1.84 - 2.0x₂ - 2.0x₁ - x₂² - x₁²", + "text/latex": "$$ -1.84 - 2.0x_{2} - 2.0x_{1} - x_{2}^{2} - x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "g₁ = -(x[1]+1)^2 - (x[2]+1)^2 + 0.16 # 𝒳ᵤ = {x ∈ R²: g₁(x) ≥ 0}" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "Semi-algebraic function describing the initial set 𝒳₀" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "-2.0 + 3.0x₁ - x₂² - x₁²", + "text/latex": "$$ -2.0 + 3.0x_{1} - x_{2}^{2} - x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "h₁ = -(x[1]-1.5)^2 - x[2]^2 + 0.25 # 𝒳₀ = {x ∈ R²: h₁(x) ≥ 0}" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "Define SOS barrier function B" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1]) + (_[2])x₂ + (_[3])x₁ + (_[4])x₂² + (_[5])x₁x₂ + (_[6])x₁² + (_[7])x₂³ + (_[8])x₁x₂² + (_[9])x₁²x₂ + (_[10])x₁³ + (_[11])x₂⁴ + (_[12])x₁x₂³ + (_[13])x₁²x₂² + (_[14])x₁³x₂ + (_[15])x₁⁴", + "text/latex": "$$ ({\\_}_{1}) + ({\\_}_{2})x_{2} + ({\\_}_{3})x_{1} + ({\\_}_{4})x_{2}^{2} + ({\\_}_{5})x_{1}x_{2} + ({\\_}_{6})x_{1}^{2} + ({\\_}_{7})x_{2}^{3} + ({\\_}_{8})x_{1}x_{2}^{2} + ({\\_}_{9})x_{1}^{2}x_{2} + ({\\_}_{10})x_{1}^{3} + ({\\_}_{11})x_{2}^{4} + ({\\_}_{12})x_{1}x_{2}^{3} + ({\\_}_{13})x_{1}^{2}x_{2}^{2} + ({\\_}_{14})x_{1}^{3}x_{2} + ({\\_}_{15})x_{1}^{4} $$" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "monos = monomials(x, 0:4)\n", + "@variable(model, B, Poly(monos))" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "Define barrier certificate constraints using SOS relaxation" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "B(x) > 0 for all x ∈ 𝒳ᵤ" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1] - 0.001) + (_[2])x₂ + (_[3])x₁ + (_[4])x₂² + (_[5])x₁x₂ + (_[6])x₁² + (_[7])x₂³ + (_[8])x₁x₂² + (_[9])x₁²x₂ + (_[10])x₁³ + (_[11])x₂⁴ + (_[12])x₁x₂³ + (_[13])x₁²x₂² + (_[14])x₁³x₂ + (_[15])x₁⁴ is SOS", + "text/latex": "$$ ({\\_}_{1} - 0.001) + ({\\_}_{2})x_{2} + ({\\_}_{3})x_{1} + ({\\_}_{4})x_{2}^{2} + ({\\_}_{5})x_{1}x_{2} + ({\\_}_{6})x_{1}^{2} + ({\\_}_{7})x_{2}^{3} + ({\\_}_{8})x_{1}x_{2}^{2} + ({\\_}_{9})x_{1}^{2}x_{2} + ({\\_}_{10})x_{1}^{3} + ({\\_}_{11})x_{2}^{4} + ({\\_}_{12})x_{1}x_{2}^{3} + ({\\_}_{13})x_{1}^{2}x_{2}^{2} + ({\\_}_{14})x_{1}^{3}x_{2} + ({\\_}_{15})x_{1}^{4} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "ε = 0.001\n", + "@constraint(model, B >= ε, domain = @set(g₁ >= 0))" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "B(x) ≤ 0 for all x ∈ 𝒳₀" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-_[1]) + (-_[2])x₂ + (-_[3])x₁ + (-_[4])x₂² + (-_[5])x₁x₂ + (-_[6])x₁² + (-_[7])x₂³ + (-_[8])x₁x₂² + (-_[9])x₁²x₂ + (-_[10])x₁³ + (-_[11])x₂⁴ + (-_[12])x₁x₂³ + (-_[13])x₁²x₂² + (-_[14])x₁³x₂ + (-_[15])x₁⁴ is SOS", + "text/latex": "$$ (-{\\_}_{1}) + (-{\\_}_{2})x_{2} + (-{\\_}_{3})x_{1} + (-{\\_}_{4})x_{2}^{2} + (-{\\_}_{5})x_{1}x_{2} + (-{\\_}_{6})x_{1}^{2} + (-{\\_}_{7})x_{2}^{3} + (-{\\_}_{8})x_{1}x_{2}^{2} + (-{\\_}_{9})x_{1}^{2}x_{2} + (-{\\_}_{10})x_{1}^{3} + (-{\\_}_{11})x_{2}^{4} + (-{\\_}_{12})x_{1}x_{2}^{3} + (-{\\_}_{13})x_{1}^{2}x_{2}^{2} + (-{\\_}_{14})x_{1}^{3}x_{2} + (-{\\_}_{15})x_{1}^{4} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "@constraint(model, B <= 0, domain = @set(h₁ >= 0))" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "Ḃ(x) ≤ 0 for all x ∈ R²" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[2] - _[3])x₂ + (_[2])x₁ + (2 _[4] - _[5])x₂² + (2 _[4] + _[5] - 2 _[6])x₁x₂ + (_[5])x₁² + (3 _[7] - _[8])x₂³ + (3 _[7] + 2 _[8] - 2 _[9])x₁x₂² + (2 _[8] + _[9] - 3 _[10])x₁²x₂ + (-0.3333333333333333 _[2] + _[9])x₁³ + (4 _[11] - _[12])x₂⁴ + (4 _[11] + 3 _[12] - 2 _[13])x₁x₂³ + (3 _[12] + 2 _[13] - 3 _[14])x₁²x₂² + (-0.6666666666666666 _[4] + 2 _[13] + _[14] - 4 _[15])x₁³x₂ + (-0.3333333333333333 _[5] + _[14])x₁⁴ + (-_[7])x₁³x₂² + (-0.6666666666666666 _[8])x₁⁴x₂ + (-0.3333333333333333 _[9])x₁⁵ + (-1.3333333333333333 _[11])x₁³x₂³ + (-_[12])x₁⁴x₂² + (-0.6666666666666666 _[13])x₁⁵x₂ + (-0.3333333333333333 _[14])x₁⁶ is SOS", + "text/latex": "$$ ({\\_}_{2} - {\\_}_{3})x_{2} + ({\\_}_{2})x_{1} + (2 {\\_}_{4} - {\\_}_{5})x_{2}^{2} + (2 {\\_}_{4} + {\\_}_{5} - 2 {\\_}_{6})x_{1}x_{2} + ({\\_}_{5})x_{1}^{2} + (3 {\\_}_{7} - {\\_}_{8})x_{2}^{3} + (3 {\\_}_{7} + 2 {\\_}_{8} - 2 {\\_}_{9})x_{1}x_{2}^{2} + (2 {\\_}_{8} + {\\_}_{9} - 3 {\\_}_{10})x_{1}^{2}x_{2} + (-0.3333333333333333 {\\_}_{2} + {\\_}_{9})x_{1}^{3} + (4 {\\_}_{11} - {\\_}_{12})x_{2}^{4} + (4 {\\_}_{11} + 3 {\\_}_{12} - 2 {\\_}_{13})x_{1}x_{2}^{3} + (3 {\\_}_{12} + 2 {\\_}_{13} - 3 {\\_}_{14})x_{1}^{2}x_{2}^{2} + (-0.6666666666666666 {\\_}_{4} + 2 {\\_}_{13} + {\\_}_{14} - 4 {\\_}_{15})x_{1}^{3}x_{2} + (-0.3333333333333333 {\\_}_{5} + {\\_}_{14})x_{1}^{4} + (-{\\_}_{7})x_{1}^{3}x_{2}^{2} + (-0.6666666666666666 {\\_}_{8})x_{1}^{4}x_{2} + (-0.3333333333333333 {\\_}_{9})x_{1}^{5} + (-1.3333333333333333 {\\_}_{11})x_{1}^{3}x_{2}^{3} + (-{\\_}_{12})x_{1}^{4}x_{2}^{2} + (-0.6666666666666666 {\\_}_{13})x_{1}^{5}x_{2} + (-0.3333333333333333 {\\_}_{14})x_{1}^{6} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra # Needed for `dot`\n", + "dBdt = dot(differentiate(B, x), f)\n", + "@constraint(model, -dBdt >= 0)" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "The model is ready to be optimized by the solver:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "JuMP.optimize!(model)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "We verify that the solver has found a feasible solution:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "JuMP.primal_status(model)" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "Plot the phase plot with the 0-level set of the barrier function, and the boundary of the initial and unsafe sets" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: To maintain consistency with solution indexing, keyword argument vars will be removed in a future version. Please use keyword argument idxs instead.\n", + "│ caller = ip:0x0\n", + "└ @ Core :-1\n", + "┌ Warning: Interrupted. Larger maxiters is needed. If you are using an integrator for non-stiff ODEs or an automatic switching algorithm (the default), you may want to consider using a method for stiff equations. See the solver pages for more details (e.g. https://docs.sciml.ai/DiffEqDocs/stable/solvers/ode_solve/#Stiff-Problems).\n", + "└ @ SciMLBase ~/.julia/packages/SciMLBase/hSv8d/src/integrator_interface.jl:597\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=49}", + "image/png": "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", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "import DifferentialEquations, Plots, ImplicitPlots\n", + "function phase_plot(f, B, g₁, h₁, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5())\n", + " X₀plot = ImplicitPlots.implicit_plot(h₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label=\"X₀\", linecolor=:blue)\n", + " Xᵤplot = ImplicitPlots.implicit_plot!(g₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label=\"Xᵤ\", linecolor=:teal)\n", + " Bplot = ImplicitPlots.implicit_plot!(B; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label=\"B = 0\", linecolor=:red)\n", + " Plots.plot(X₀plot)\n", + " Plots.plot!(Xᵤplot)\n", + " Plots.plot!(Bplot)\n", + " ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f]\n", + " ∇pt(v, p, t) = ∇(v[1], v[2])\n", + " function traj(v0)\n", + " tspan = (0.0, Δt)\n", + " prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan)\n", + " return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8)\n", + " end\n", + " ticks = -5:0.5:5\n", + " X = repeat(ticks, 1, length(ticks))\n", + " Y = X'\n", + " Plots.quiver!(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5)\n", + " for x0 in X0\n", + " Plots.plot!(traj(x0), vars=(1, 2), label = nothing)\n", + " end\n", + " Plots.plot!(xlims = (-2, 3), ylims = (-2.5, 2.5))\n", + "end\n", + "\n", + "phase_plot(f, value(B), g₁, h₁, 10, 30.0, [[x1, x2] for x1 in 1.2:0.2:1.7, x2 in -0.35:0.1:0.35])" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Systems and Control/barrier_certificate.jl b/previews/PR347/generated/Systems and Control/barrier_certificate.jl new file mode 100644 index 000000000..0324d0f74 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/barrier_certificate.jl @@ -0,0 +1,60 @@ +using DynamicPolynomials +@polyvar x[1:2] + +using SumOfSquares +using CSDP + +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +f = [ x[2], + -x[1] + (1/3)*x[1]^3 - x[2]] + +g₁ = -(x[1]+1)^2 - (x[2]+1)^2 + 0.16 # 𝒳ᵤ = {x ∈ R²: g₁(x) ≥ 0} + +h₁ = -(x[1]-1.5)^2 - x[2]^2 + 0.25 # 𝒳₀ = {x ∈ R²: h₁(x) ≥ 0} + +monos = monomials(x, 0:4) +@variable(model, B, Poly(monos)) + +ε = 0.001 +@constraint(model, B >= ε, domain = @set(g₁ >= 0)) + +@constraint(model, B <= 0, domain = @set(h₁ >= 0)) + +using LinearAlgebra # Needed for `dot` +dBdt = dot(differentiate(B, x), f) +@constraint(model, -dBdt >= 0) + +JuMP.optimize!(model) + +JuMP.primal_status(model) + +import DifferentialEquations, Plots, ImplicitPlots +function phase_plot(f, B, g₁, h₁, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5()) + X₀plot = ImplicitPlots.implicit_plot(h₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="X₀", linecolor=:blue) + Xᵤplot = ImplicitPlots.implicit_plot!(g₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="Xᵤ", linecolor=:teal) + Bplot = ImplicitPlots.implicit_plot!(B; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="B = 0", linecolor=:red) + Plots.plot(X₀plot) + Plots.plot!(Xᵤplot) + Plots.plot!(Bplot) + ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f] + ∇pt(v, p, t) = ∇(v[1], v[2]) + function traj(v0) + tspan = (0.0, Δt) + prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan) + return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8) + end + ticks = -5:0.5:5 + X = repeat(ticks, 1, length(ticks)) + Y = X' + Plots.quiver!(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5) + for x0 in X0 + Plots.plot!(traj(x0), vars=(1, 2), label = nothing) + end + Plots.plot!(xlims = (-2, 3), ylims = (-2.5, 2.5)) +end + +phase_plot(f, value(B), g₁, h₁, 10, 30.0, [[x1, x2] for x1 in 1.2:0.2:1.7, x2 in -0.35:0.1:0.35]) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Systems and Control/barrier_certificate/d58b6113.svg b/previews/PR347/generated/Systems and Control/barrier_certificate/d58b6113.svg new file mode 100644 index 000000000..adf5aa936 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/barrier_certificate/d58b6113.svg @@ -0,0 +1,1400 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/barrier_certificate/index.html b/previews/PR347/generated/Systems and Control/barrier_certificate/index.html new file mode 100644 index 000000000..f3002b2cb --- /dev/null +++ b/previews/PR347/generated/Systems and Control/barrier_certificate/index.html @@ -0,0 +1,39 @@ + +Barrier certificates for collision avoidance · SumOfSquares

Barrier certificates for collision avoidance

Adapted from: Example 2 of "Engineering applications of SOS polynomials" by Georgina Hall, from the 2019 AMS Short Course on Sum of Squares: Theory and Applications Implementation by: Hugo Tadashi Kussaba

using DynamicPolynomials
+@polyvar x[1:2]
+
+using SumOfSquares
+using CSDP

We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.

solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = SOSModel(solver);

We define below the vector field $\text{d}x/\text{d}t = f$

f = [ x[2],
+     -x[1] + (1/3)*x[1]^3 - x[2]]
2-element Vector{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Float64}}:
+ x₂
+ -x₂ - x₁ + 0.3333333333333333x₁³

Semi-algebraic function describing the unsafe set 𝒳ᵤ

g₁ = -(x[1]+1)^2 - (x[2]+1)^2 + 0.16  # 𝒳ᵤ = {x ∈ R²: g₁(x) ≥ 0}

\[ -1.84 - 2.0x_{2} - 2.0x_{1} - x_{2}^{2} - x_{1}^{2} \]

Semi-algebraic function describing the initial set 𝒳₀

h₁ = -(x[1]-1.5)^2 - x[2]^2 + 0.25    # 𝒳₀ = {x ∈ R²: h₁(x) ≥ 0}

\[ -2.0 + 3.0x_{1} - x_{2}^{2} - x_{1}^{2} \]

Define SOS barrier function B

monos = monomials(x, 0:4)
+@variable(model, B, Poly(monos))

\[ ({\_}_{1}) + ({\_}_{2})x_{2} + ({\_}_{3})x_{1} + ({\_}_{4})x_{2}^{2} + ({\_}_{5})x_{1}x_{2} + ({\_}_{6})x_{1}^{2} + ({\_}_{7})x_{2}^{3} + ({\_}_{8})x_{1}x_{2}^{2} + ({\_}_{9})x_{1}^{2}x_{2} + ({\_}_{10})x_{1}^{3} + ({\_}_{11})x_{2}^{4} + ({\_}_{12})x_{1}x_{2}^{3} + ({\_}_{13})x_{1}^{2}x_{2}^{2} + ({\_}_{14})x_{1}^{3}x_{2} + ({\_}_{15})x_{1}^{4} \]

Define barrier certificate constraints using SOS relaxation

B(x) > 0 for all x ∈ 𝒳ᵤ

ε = 0.001
+@constraint(model, B >= ε, domain = @set(g₁ >= 0))

\[ ({\_}_{1} - 0.001) + ({\_}_{2})x_{2} + ({\_}_{3})x_{1} + ({\_}_{4})x_{2}^{2} + ({\_}_{5})x_{1}x_{2} + ({\_}_{6})x_{1}^{2} + ({\_}_{7})x_{2}^{3} + ({\_}_{8})x_{1}x_{2}^{2} + ({\_}_{9})x_{1}^{2}x_{2} + ({\_}_{10})x_{1}^{3} + ({\_}_{11})x_{2}^{4} + ({\_}_{12})x_{1}x_{2}^{3} + ({\_}_{13})x_{1}^{2}x_{2}^{2} + ({\_}_{14})x_{1}^{3}x_{2} + ({\_}_{15})x_{1}^{4} \text{ is SOS} \]

B(x) ≤ 0 for all x ∈ 𝒳₀

@constraint(model, B <= 0, domain = @set(h₁ >= 0))

\[ (-{\_}_{1}) + (-{\_}_{2})x_{2} + (-{\_}_{3})x_{1} + (-{\_}_{4})x_{2}^{2} + (-{\_}_{5})x_{1}x_{2} + (-{\_}_{6})x_{1}^{2} + (-{\_}_{7})x_{2}^{3} + (-{\_}_{8})x_{1}x_{2}^{2} + (-{\_}_{9})x_{1}^{2}x_{2} + (-{\_}_{10})x_{1}^{3} + (-{\_}_{11})x_{2}^{4} + (-{\_}_{12})x_{1}x_{2}^{3} + (-{\_}_{13})x_{1}^{2}x_{2}^{2} + (-{\_}_{14})x_{1}^{3}x_{2} + (-{\_}_{15})x_{1}^{4} \text{ is SOS} \]

Ḃ(x) ≤ 0 for all x ∈ R²

using LinearAlgebra # Needed for `dot`
+dBdt = dot(differentiate(B, x), f)
+@constraint(model, -dBdt >= 0)

\[ ({\_}_{2} - {\_}_{3})x_{2} + ({\_}_{2})x_{1} + (2 {\_}_{4} - {\_}_{5})x_{2}^{2} + (2 {\_}_{4} + {\_}_{5} - 2 {\_}_{6})x_{1}x_{2} + ({\_}_{5})x_{1}^{2} + (3 {\_}_{7} - {\_}_{8})x_{2}^{3} + (3 {\_}_{7} + 2 {\_}_{8} - 2 {\_}_{9})x_{1}x_{2}^{2} + (2 {\_}_{8} + {\_}_{9} - 3 {\_}_{10})x_{1}^{2}x_{2} + (-0.3333333333333333 {\_}_{2} + {\_}_{9})x_{1}^{3} + (4 {\_}_{11} - {\_}_{12})x_{2}^{4} + (4 {\_}_{11} + 3 {\_}_{12} - 2 {\_}_{13})x_{1}x_{2}^{3} + (3 {\_}_{12} + 2 {\_}_{13} - 3 {\_}_{14})x_{1}^{2}x_{2}^{2} + (-0.6666666666666666 {\_}_{4} + 2 {\_}_{13} + {\_}_{14} - 4 {\_}_{15})x_{1}^{3}x_{2} + (-0.3333333333333333 {\_}_{5} + {\_}_{14})x_{1}^{4} + (-{\_}_{7})x_{1}^{3}x_{2}^{2} + (-0.6666666666666666 {\_}_{8})x_{1}^{4}x_{2} + (-0.3333333333333333 {\_}_{9})x_{1}^{5} + (-1.3333333333333333 {\_}_{11})x_{1}^{3}x_{2}^{3} + (-{\_}_{12})x_{1}^{4}x_{2}^{2} + (-0.6666666666666666 {\_}_{13})x_{1}^{5}x_{2} + (-0.3333333333333333 {\_}_{14})x_{1}^{6} \text{ is SOS} \]

The model is ready to be optimized by the solver:

JuMP.optimize!(model)

We verify that the solver has found a feasible solution:

JuMP.primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

Plot the phase plot with the 0-level set of the barrier function, and the boundary of the initial and unsafe sets

import DifferentialEquations, Plots, ImplicitPlots
+function phase_plot(f, B, g₁, h₁, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5())
+    X₀plot = ImplicitPlots.implicit_plot(h₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="X₀", linecolor=:blue)
+    Xᵤplot = ImplicitPlots.implicit_plot!(g₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="Xᵤ", linecolor=:teal)
+    Bplot  = ImplicitPlots.implicit_plot!(B; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="B = 0", linecolor=:red)
+    Plots.plot(X₀plot)
+    Plots.plot!(Xᵤplot)
+    Plots.plot!(Bplot)
+    ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f]
+    ∇pt(v, p, t) = ∇(v[1], v[2])
+    function traj(v0)
+        tspan = (0.0, Δt)
+        prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan)
+        return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8)
+    end
+    ticks = -5:0.5:5
+    X = repeat(ticks, 1, length(ticks))
+    Y = X'
+    Plots.quiver!(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5)
+    for x0 in X0
+        Plots.plot!(traj(x0), vars=(1, 2), label = nothing)
+    end
+    Plots.plot!(xlims = (-2, 3), ylims = (-2.5, 2.5))
+end
+
+phase_plot(f, value(B), g₁, h₁, 10, 30.0, [[x1, x2] for x1 in 1.2:0.2:1.7, x2 in -0.35:0.1:0.35])
Example block output

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Systems and Control/julia_set.ipynb b/previews/PR347/generated/Systems and Control/julia_set.ipynb new file mode 100644 index 000000000..48f6a4cf7 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set.ipynb @@ -0,0 +1,57206 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Outer approximation of Julia set" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Section 7.1.3 of [KHJ14]\n", + "\n", + "[KHJ14] Milan Korda, Didier Henrion, and Colin N. Jones.\n", + "*Convex computation of the maximum controlled invariant set for polynomial control systems*.\n", + "SIAM Journal on Control and Optimization 52.5 (2014): 2944-2969." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "The Julia map is defined as follows:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "julia_map (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "function julia_map(point, c)\n", + " a, b = point\n", + " return [a^2 - b^2 + real(c), 2a * b + imag(c)]\n", + "end" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "The *escape radius\" is the radius `r` such that `r^2 ≥ r + abs(c)`.\n", + "Ouside of the circle of that radius, all points diverge so we know the Julia set belongs to that circle." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "escape_radius (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "escape_radius(c) = (1 + √(1 + 4 * abs(c))) / 2" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "To check whether a point is in the Julia set, we can iterate and once the point leaves the circle of escape radius,\n", + "we consider that it is not in the Julia set, if it stays in the set, we consider that it is in the Julia set.\n", + "This gives an outer approximation that converges to the Julia set when `m` increases." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "in_set (generic function with 2 methods)" + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra\n", + "function in_set(x, c, m=2000)\n", + " r = escape_radius(c)\n", + " for i in 1:m\n", + " if norm(x) > r\n", + " return false\n", + " end\n", + " x = julia_map(x, c)\n", + " end\n", + " return true\n", + "end" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "To sort of minimize a level set of a polynomial we minimize integral of that polynomial.\n", + "We borrow the following from https://doi.org/10.1080/00029890.2001.11919774" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "disk_integral (generic function with 2 methods)" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "using SpecialFunctions\n", + "using DynamicPolynomials\n", + "β(α) = (α + 1) / 2\n", + "function circle_integral(mono::AbstractMonomial)\n", + " if any(isodd, exponents(mono))\n", + " return 0.0\n", + " else\n", + " return 2 * prod(gamma ∘ β, exponents(mono)) / gamma(sum(β, exponents(mono)))\n", + " end\n", + "end\n", + "function disk_integral(mono::AbstractMonomial, r)\n", + " d = degree(mono) + nvariables(mono)\n", + " return circle_integral(mono) * r^d / d\n", + "end\n", + "function disk_integral(p::AbstractPolynomialLike, r)\n", + " return sum(MultivariatePolynomials.coefficient(t) * disk_integral(monomial(t), r) for t in terms(p))\n", + "end" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "The following function implements [KHJ14, (8)]." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "outer_approximation (generic function with 1 method)" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "function outer_approximation(solver, d::Int, c; α = 1/2)\n", + " @polyvar x[1:2]\n", + " model = SOSModel(solver)\n", + " r = escape_radius(c)\n", + " S = @set sum(x.^2) <= r^2\n", + " @variable(model, v, Poly(monomials(x, 0:2d)))\n", + " @variable(model, w0, SOSPoly(monomials(x, 0:d)))\n", + " @variable(model, w1, SOSPoly(monomials(x, 0:(d - 1))))\n", + " @constraint(model, α * v(x => julia_map(x, c)) <= v, domain = S)\n", + " w = w0 + w1 * (r^2 - sum(x.^2))\n", + " @constraint(model, w >= v + 1, domain = S)\n", + " @objective(model, Min, disk_integral(w, r))\n", + " optimize!(model)\n", + " if primal_status(model) == MOI.NO_SOLUTION\n", + " return\n", + " end\n", + " return model\n", + "end" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "The following function plots the Julia set with the outer approximation." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "julia_plot (generic function with 3 methods)" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "using ImplicitPlots\n", + "using Plots\n", + "function julia_plot(poly, c, n=200, m=1000; tol=1e-6, res = 1000)\n", + " r = escape_radius(c)\n", + " p = implicit_plot(poly; xlims=(-r, r) .* 1.1, ylims=(-r, r), resolution = res, label=\"\")\n", + " θ = range(0, stop=2π, length=100)\n", + " points = Vector{Float64}[]\n", + " as = range(-r, r, length=n)\n", + " bs = range(-r, r, length=n)\n", + " for a in as, b in bs\n", + " point = [a, b]\n", + " if in_set(point, c, m)\n", + " push!(points, point)\n", + " end\n", + " end\n", + " xs = [point[1] for point in points]\n", + " ys = [point[2] for point in points]\n", + " scatter!(p, xs, ys, label=\"\", markerstrokewidth=0, markersize=1.5, m=:pixel)\n", + " return p\n", + "end" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "MathOptInterface.OptimizerWithAttributes(CSDP.Optimizer, Pair{MathOptInterface.AbstractOptimizerAttribute, Any}[MathOptInterface.Silent() => true])" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "import CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "Let's start with the value of `c` corresponding to the left image of [KHJ14, Figure 3] and with degree 2." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 6.02400e+00\n Dual objective value : 6.02400e+00\n\n* Work counters\n Solve time (sec) : 1.44560e-02\n" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "c = -0.7 + 0.2im\n", + "model = outer_approximation(solver, 2, c)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "We visualize below:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: Skipped marker arg pixel.\n", + "└ @ Plots ~/.julia/packages/Plots/ju9dp/src/args.jl:1149\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=2}", + "image/png": "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uuqqOmUeq1atmjNnDud81qxZPXv2jL6Fh7N3795nn312//7906ZNGzdu3OENnnvuuXAyzO7du5966qlRte8whBDr1q1btmxZWVnZFVdcUafwQAjx8ssvr1ixolu3bpdffnlLCCUtLS1dunTp+vXr+/XrN3z48MMbrF69+quvvgq/nTFjRqsTZUUBmhG2LH766adRo0Y9+eSTs2fPrqioqLPNbbfd9u23327atGnTpk27d++OsoV1cuqpp95999233nrrokWL6mywYMGCCRMm5OTklJaWDh06tCWYvXfv3qFDhx48eDAvL2/y5MlffPFFrQZVVVWzZ8/euHGjGuri4uKY2PnQQw/9+te/7tKly8KFC8ePHy+EqNVg1apVI0eO9Pv9uq4PHz68JSTzrKysHDFixPr16zt27Dhz5szXX3/98DbXX3/9ihUr1Nju3bs3+kbW4rvvvjv11FOfeOKJ2bNnHz7IiptuuumRRx7p1q3b66+/ftFFF0XZwjq54oorbrrppnvuueeNN96os8FXX3314IMPbgphWVaULWwdSKIl4bqulFL5iQMHDtTZpqCgYNmyZdG16ygoswsLC//5z3/W2WDq1Kn33Xefej1jxoy77roresbVw913333mmWeq1w888MDkyZNrNTh06BAAx3Giblo1lmXl5+fPmzdPSmnbdqdOnT766KNabS6//PKbbrpJvb722muvueaaaFt5GM8+++ywYcPU6zlz5gwYMODwNomJidu3b4+uXUdCfYfXr18PwLbtwxvs27fP7/dv2rRJSllSUpKYmLhmzZpoW3kYyuwrr7zylltuqbPBU089de6550bXqNYHzQhbFg3MBPHaa6899NBDX375ZTOb01COavaCBQsmTZqkXk+cOHH+/PnNb9RRWLBgwcSJE9XriRMnLliwoM5mjz/++GOPPbZixYoomlbNunXriouLx44dC0DX9dNOO+3woZs/f35kR1rg2K5YseLgwYOHN3vhhRcefvjhb7/9NrrW1c1Rv8OLFi3q0KFD586dAaSmpg4bNqy+70w0achvjK1bt95///3PP/98rFY1Wj7kCFsfQ4cOdV13+/btM2fOnD17dqzNOTplZWXl5eVt2rRRb3NyclpCUbqioqJIk6qqqmr9smaMTZo0ae/evT/++OOYMWMeffTR6Bu5e/furKyscNab3NzcXbt21WpTqyMtbWyV/YdbNWbMmPLy8o0bN06bNu2OO+6Iuo2NJrJTqOezaIGkp6f37t27pKRk7ty53bt3X716dawtaolQsEy02bBhQ53hDB9++GH4j+gjE94MuOGGG3r06HHDDTf06dOnKU2si169eqlVo0huvPHGBx544KjX6roOIBwZ4ThOdKIM3n777XPPPffw49u3b8/Pz9d1PdIkALUS2qWmpn788cfq9YwZM84+++yrr746yvERkUYCsG378PipWh1pCREckSYJIYQQh1v10UcfqRdXXnnloEGDrrvuury8vKha2Uh0XY/Mktha8q6df/75559/vnp9+eWX//GPf3zllVdia1ILhBxhtOnatWtTVY7u1KlTu3btNm/eHAVHeDx/SCYkJGRmZu7cuVPl4965c2fbtm2bzLL6Ofvss48w1O3atQv/Rb9z5860tLTk5OT6Go8aNSoQCBQVFUU53rVt27bFxcVVVVUJCQkAdu7c2aNHj1ptanUkOmN7ZGqZBCA/P7++xv37909MTNyyZUsLd4Tt2rVTfVHs3LnzzDPPjKE9x8DIkSOfeeaZWFvREqGl0dbBqlWrNmzYACAYDMpQetjly5fv2LGjV69eMTWtXnbv3h0OIj3jjDPmzp0LQAjx5ptvnnHGGTE1zTPp3//+t4oPnDt3btikRYsWqXW8QCAQbvzee++lpaVFv9pD165du3Xr9tZbbwE4dOjQp59+qn75FhcXhzeozjzzTDW2qNmRGHLGGWe8++67agDfeOON8ePHJyUlAVi+fPnWrVtRc2y/+OILy7K6desWK2uPzIoVKzZv3gxg9OjRFRUV33zzDYDNmzf/8MMPLUG5VCcVFRXz5s1T3+3wUAsh3n///b59+8bUtJZKrKN1iNoUFhb2798fwIABA4YPH64Onn/++Soy8Msvv+zcufP5559/zjnnpKSk3H333TE11uOGG24oLCxMTEzs3LlzYWHhokWLpJTPP/989+7dVYM1a9bk5uaef/75p5xyyuDBg8vLy2Nqr5RSVlRUDBkyZOzYsT//+c9zc3NXr16tjvfq1evZZ5+VUj722GP9+vWbNWvWpEmTUlNTX3vttZjY+e6772ZnZ1966aW9e/e++OKL1cGPPvooJSVFvd61a1enTp2mT58+derUrl277tmzJyZ2RuI4zsSJE4cMGTJr1qysrKyFCxeq46eddpr6xr7xxhs9evS44IILpk+fnpyc/MQTT8TUXimlrKioKCwsVH5i8ODB48aNU8dPP/303/3ud+r1E088kZube9lll3Xs2PHOO++MnbHVPPHEE4WFhdnZ2bm5uYWFhS+++KKU8ocffgCgfsrGjx8/YcKEWbNm9enTp2fPnjt27Ii1yS0Rqj7R4liyZEn4NWNs8ODBADZu3GgYRkFBgRBi5cqVa9euNU1z0KBBLUSZvmHDhpKSkvDbbt26paam7t+/v6ioqF+/furgwYMHP/vss+Tk5HHjxrWQWjyWZX3++efl5eUTJkzIyMhQB1euXJmfn5+dnW1Z1pIlS7Zs2ZKenj5kyJDIQIkos3Xr1oULF7Zv33706NGMMQClpaXr168vLCxUDcrLyz/77DPG2IQJE9TcK+a4rvvFF18cOHDglFNOCa95rlmzJi0tLT8/33Gc5cuXb9iwISkpaciQIUdYOI0arusuX748/FbX9QEDBgBYt25dUlJSu3bt1PGffvppxYoV3bt3Dw9+bNm1a1dkIFK7du3y8vKqqqpWrlw5ZMgQzvmBAwe+++67Q4cOtW/ffsSIEWrDnqgFOUKCIAgirqE9QoIgCCKuIUdIEARBxDXkCAmCIIi4hhwhQRAEEdeQIyQIgiDiGnKEBEEQRFxDjpAgCIKIa8gREgRBEHENOUKCIAgiriFHSBAEQcQ15AgJgiCIuOb/A9GaGpRb4zILAAAAAElFTkSuQmCC", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "julia_plot(value(model[:v]), c)" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "Let's now look at degree 4." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : ALMOST_OPTIMAL\n Message from the solver:\n \"Problem solved to near optimality.\"\n\n* Candidate solution (result #1)\n Primal status : NEARLY_FEASIBLE_POINT\n Dual status : NEARLY_FEASIBLE_POINT\n Objective value : 5.03023e+00\n Dual objective value : 5.03038e+00\n\n* Work counters\n Solve time (sec) : 3.64797e-01\n" + }, + "metadata": {}, + "execution_count": 10 + } + ], + "cell_type": "code", + "source": [ + "model = outer_approximation(solver, 4, c)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "We visualize below:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: Skipped marker arg pixel.\n", + "└ @ Plots ~/.julia/packages/Plots/ju9dp/src/args.jl:1149\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=2}", + "image/png": "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QRAEkdKQIyQIgiBSGnKEBEEQREpDjrCdsnbt2jfffDPZVjSbe+65J9kmNJu33377888/T7YVzaOiouKxxx5LthXN5plnniktLU22Fc1j8+bNL774YrKtaDb333+/4zjJtqLDQI6wnbJixYqO6Ajvuusu13WTbUXzeOeddz7++ONkW9E8du3a9eSTTybbimbzwgsvbNy4MdlWNI9Vq1a99tprybai2TzwwAPl5eXJtqLDQI6QIAiCSGnIERIEQRApDTlCgiAIIqVhUspk2/DtJxQK5eTkFBcXN/2UysrKSCSSl5d34qw6EXz99dc9e/ZMthXN49ChQ6ZpZmRkJNuQZmDb9r59+7p165ZsQ5pHaWlpTk6O3+9PtiHNoKqqqqqqKj8/P9mGNI+dO3d269aN82YMdWbOnNkRg91aBXKEbcSOHTuaFUUihHBd1zCME2fSiSASifh8vmRb0Twcx2GMaZqWbEOaR0d81B3RZimlbdumaSbbkObRgkddWFgYDAZPkD3tHHKEBEEQREpDa4QEQRBESkOOkCAIgkhpyBESBEEQKQ05QoIgCCKl0ZNtAFELKeXmzZs///zzioqK73//+/XGfT3//POhUEhtFxcXT506tW1trId9+/atXLly165d48eP79u3b71tPvvsswULFqSlpV111VU9evRoYwvrZefOnU899VQoFLrkkktGjRpV56hlWU8//XTs5amnnnp0m7bh1VdfXbZsWVFR0Q9+8IN6ZR5fffXVc889xzmfPXv2gAED2t7Co9m/f/8TTzxx8ODBc845Z/z48Uc3ePLJJ2PJMPv163fWWWe1qX1HIYTYtGnTqlWrKisrr7322nqFB0KIZ599ds2aNSUlJddcc017CCWtqKj4/PPPN2/ePGjQoNGjRx/dYP369R9++GHs5cyZMzucKKsNoBFh+2LdunWnn376Y489Nnfu3Kqqqnrb3HrrrZ988sm2bdu2bdu2d+/eNrawXs4666x58+bdcsstK1asqLfB8uXLJ06cmJ+fX1FRMXLkyPZg9v79+0eOHHn48OHCwsIpU6YsXbq0ToOampq5c+du3bpVPeqysrKk2Hn//fffdNNNffr0+eijjyZMmCCEqNPgq6++GjNmjN/v13V99OjR7SGZZ3V19WmnnbZ58+YePXpcdtll8+fPP7rN9ddfv2bNGvVs9+/f3/ZG1uHTTz8966yzHn300blz5x79kBU33njjAw88UFJSMn/+/CuuuKKNLayXa6+99sYbb7zrrrsWLlxYb4MPP/zwvvvu2xbFsqw2trBjIIn2hOu6UkrlJw4dOlRvm+Li4lWrVrWtXY2gzB4+fPi//vWvehtMnz797rvvVtszZ86888472864Bpg3b955552ntu+9994pU6bUaXDkyBEAjuO0uWlxLMvq0qXLkiVLpJS2bffs2fOtt96q0+aaa6658cYb1faPf/zj6667rq2tPIonnnhi1KhRavu5554bMmTI0W2CweA333zTtnYdC/UZ3rx5MwDbto9ucODAAb/fv23bNilleXl5MBjcsGFDW1t5FMrsOXPm3HzzzfU2ePzxxy+++OK2NarjQSPC9kUTM0G88MIL999//wcffHCCzWkqjZq9fPnyyZMnq+1JkyYtW7bsxBvVCMuXL580aZLanjRp0vLly+tt9vDDDz/00ENr1qxpQ9PibNq0qaysbNy4cQB0XT/77LOPfnTLli1L7Eg7fLZr1qw5fPjw0c2efvrpv/71r5988knbWlc/jX6GV6xY0b179169egHIzMwcNWpUQ5+ZtqQpfzF27Nhxzz33PPXUU8ma1Wj/kCPseIwcOdJ13W+++eayyy6bO3duss1pnMrKylAo1LlzZ/UyPz+/PRSlKy0tTTSppqamzh9rxtjkyZP379//5ZdfnnHGGQ8++GDbG7l3797c3NxY1puCgoI9e/bUaVOnI+3t2Sr7j7bqjDPOCIVCW7duPeecc2677bY2t7HZJHYKDbwX7ZDs7OyTTjqpvLx8wYIF/fr1W79+fbItao9QsExbs2XLlnrDGRYvXhz7EX1sYosBN9xwQ//+/W+44YaTTz65NU2sj4EDB6pZo0R++tOf3nvvvY2eq+s6gFhkhOM4bRNl8Morr1x88cVH7//mm2+6dOmi63qiSQDqJLTLzMx8++231fbMmTMvuOCCH/7wh20cH5FoJADbto+On6rTkfYQwZFokhBCCHG0VW+99ZbamDNnztChQ3/yk58UFha2qZXNRNf1xCyJHSXv2qxZs2bNmqW2r7nmmv/+7/9+/vnnk2tSO4QcYVvTt2/f1qoc3bNnz6Kiou3bt7eBIzyeH5KBQKBTp067d+9W+bh3797dtWvXVrOsYS644IJjPOqioqLYL/rdu3dnZWWlp6c31Pj0008Ph8OlpaVtHO/atWvXsrKympqaQCAAYPfu3f3796/Tpk5H2ubZHps6JgHo0qVLQ40HDx4cDAa//vrrdu4Ii4qKVF8Uu3fvPu+885JoTwsYM2bM3//+92Rb0R6hqdGOwVdffbVlyxYAkUhERtPDrl69eteuXQMHDkyqaQ2yd+/eWBDpjBkzFixYAEAI8eKLL86YMSOppnkmvfTSSyo+cMGCBTGTVqxYoebxwuFwrPGiRYuysrLavtpD3759S0pKXn75ZQBHjhx599131R/fsrKy2ALVeeedp54tanckicyYMeO1115TD3DhwoUTJkxIS0sDsHr16h07dqD2s126dKllWSUlJcmy9tisWbNm+/btAMaOHVtVVfXxxx8D2L59+xdffNEelEv1UlVVtWTJEvXZjj1qIcQbb7xxyimnJNW09kqyo3WIugwfPnzw4MEAhgwZMnr0aLVz1qxZKjLwgw8+6NWr16xZsy688MKMjIx58+Yl1ViPG264Yfjw4cFgsFevXsOHD1+xYoWU8qmnnurXr59qsGHDhoKCglmzZp155pnDhg0LhUJJtVdKKauqqkaMGDFu3Ljvfve7BQUF69evV/sHDhz4xBNPSCkfeuihQYMGzZ49e/LkyZmZmS+88EJS7Hzttdfy8vKuuuqqk0466corr1Q733rrrYyMDLW9Z8+enj17nnvuudOnT+/bt+++ffuSYmcijuNMmjRpxIgRs2fPzs3N/eijj9T+s88+W31iFy5c2L9//0svvfTcc89NT09/9NFHk2qvlFJWVVUNHz5c+Ylhw4aNHz9e7Z86depvf/tbtf3oo48WFBRcffXVPXr0uP3225NnbJxHH310+PDheXl5BQUFw4cP/+c//yml/OKLLwCob9mECRMmTpw4e/bsk08+ecCAAbt27Uq2ye0Rqj7R7li5cmVsmzE2bNgwAFu3bjUMo7i4WAixdu3ajRs3mqY5dOjQdqJM37JlS3l5eexlSUlJZmbmwYMHS0tLBw0apHYePnz4vffeS09PHz9+fDupxWNZ1vvvvx8KhSZOnJiTk6N2rl27tkuXLnl5eZZlrVy58uuvv87Ozh4xYkRioEQbs2PHjo8++qhbt25jx45ljAGoqKjYvHnz8OHDVYNQKPTee+8xxiZOnKjGXknHdd2lS5ceOnTozDPPjM15btiwISsrq0uXLo7jrF69esuWLWlpaSNGjDjGxGmb4bru6tWrYy91XR8yZAiATZs2paWlFRUVqf3r1q1bs2ZNv379Yg8/uezZsycxEKmoqKiwsLCmpmbt2rUjRozgnB86dOjTTz89cuRIt27dTjvtNLVgT9SBHCFBEASR0tAaIUEQBJHSkCMkCIIgUhpyhARBEERKQ46QIAiCSGnIERIEQRApDTlCgiAIIqUhR0gQBEGkNOQICYIgiJSGHCFBEASR0pAjJAiCIFIacoQEQRBESvP/AeN4e+ikCX0tAAAAAElFTkSuQmCC", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "julia_plot(value(model[:v]), c)" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "Let's now use the value of `c` corresponding to the right image of [KHJ14, Figure 3] and with degree 2." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"Problem solved to optimality.\"\n\n* Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : FEASIBLE_POINT\n Objective value : 6.57446e+00\n Dual objective value : 6.57446e+00\n\n* Work counters\n Solve time (sec) : 1.54369e-02\n" + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "c = -0.9 + 0.2im\n", + "model = outer_approximation(solver, 2, c)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "We visualize below:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: Skipped marker arg pixel.\n", + "└ @ Plots ~/.julia/packages/Plots/ju9dp/src/args.jl:1149\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=2}", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOydd4BV1dX2n71PuXcqTKEXEZQuVUClaWyIBbuxm5ho8hrzpWiiSYzxTWJ8o6lGY2LHWGIvqMGCBSOgItKLVGFmYHq95ZS9vj/2uWWoAwxTuOv3B8y9Z5991tm3rLv23s9agojAMAzDMJmKbG8DGIZhGKY9YUfIMAzDZDTsCBmGYZiMhh0hwzAMk9GwI2QYhmEyGnaEDMMwTEbDjpBhGIbJaNgRMgzDMBkNO0KGYRgmo2FHyDAMw2Q07AjbAs/zfvKTn7R6n63b4aHDdd32NqGlsKmHgs7yXlVKKaXa24oW4XkeZ8dsRdgRtgWRSOQf//hH6/YZj8c7y4c2Fou1twkthU1tdZRS8Xi8va1oEZ7ndZafF47jdJaPf6eAHSHDMAyT0bAjZBiGYTIadoQMwzBMRmO2twEdnWg0WlZW1rdvX9u2dz1aUlKSXP8IhUJ9+vRpW+sYhmGYg4Ud4R5pbGycPHnymjVrHMdZvnz5yJEjd21z4YUXbt68OTs7G8Dw4cNfe+21NjeTYRiGOSjYEe6RUCj017/+ddy4cQUFBXtp9vDDD8+cObPNrGIYhmFaF14j3COWZU2fPj0vL2/vzaqrq1etWtVZNogzDMMwO8ER4UEhhLjjjjsMwygtLb377ruvv/76PbX0PO/ZZ58FIKU86aST9h5ltoROJP5lUw8FncVUlaC9Ddk3Siki6iymKqWEEK3Yp5SZGxexIzwo5syZU1hYCOD9998/44wzJk+evNulRKWU67rPPPOMflhcXHzsscce5KWj0SgRdYr3bjQaNQyjva1oEWxqq6OUisVirfuVfYhwHIeIfN9vb0P2TSQS8X2/dd8AoVDIsqxW7LATwY7woNBeEMCJJ544ZsyYhQsX7tYRSimzsrJefPHFVry0ECIrK6tTOEIiys3NbW8rWgSb2uoopQzDyMnJaW9D9o12hKFQqL0N2TdSylAo1Cl+CXUKOsHXaKfAcZySkpLi4uL2NoRhGIbZPzgi3Bv33XdfY2MjET3yyCM9evS48cYbs7Ozb7nlltLS0tmzZ2/ZsuU3v/nN1KlThRCzZ8/u0qXLjBkz2ttkhmEYZv9gR7g36urq6uvrb775ZgA1NTU63fv06dPr6+sBFBUVDRo06N133wVwxhlnXHfddeFwuH0NZhiGYfYXwbU82oD6+vp+/frV1dW1Yp9NTU2dZY2woaFhnyqUDgKb2uoopaLRKK8Rti6RSITXCFuRTvA1yjAMwzCHDnaEDMMwTEbDjpBhGIbJaNgRMgzDMBkNO0KGYRgmo2FHyDAMw2Q07AgZhmGYjIYdIcMwDJPRsCNkGIZhMhp2hAzDMExGw46QYRiGyWjYETIMwzAZDTtChmEYJqNhR8gwDMNkNOwIGYZhmIyGHSHDMAyT0bAjZBiGYTIadoQMwzBMRsOOkGEYhslo2BEyDMMwGQ07QoZhGCajYUfIMAzDZDTsCBmGYZiMhh0hwzAMk9GwI2QYhmEyGnaEDMMwTEbDjpBhGIbJaNgRMgzDMBkNO0KGYRgmo2FHyDAMw2Q07AgZhmGYjIYdIcMwDJPRsCNkGIZhMhp2hAzDMExGw46QYRiGyWjYETIMwzAZDTtChmEYJqNhR8gwDMNkNOwIGYZhmIyGHSHDMAyT0bAjZBiGYTIadoQMwzBMRsOOkGEYhslo2BEyDMMwGQ07QoZhGCajYUfIMAzDZDRmexvQoWlqalq2bJnjONOnT99Tm3feeefLL78cNWrU5MmT29I2hmEYplXgiHCP/Oc//yksLLz44osvvPDCPbX50Y9+dMMNN6xfv/6yyy6766672tI8hmEYplUQRNTeNnRQGhoapJRLliw577zzKioqdm1QWlo6aNCgdevW9evXb9myZVOmTCkpKcnLy9u1ZX19fb9+/erq6lrRvKampqysLCk7wU+ZhoaG3Q5LB4RNbXWUUtFoNCcnp70N2TeO4xBRKBRqb0P2TSQSCYVChmG0tyGHCZ3ga7S9yMvL2/un96233ho9enS/fv0AjBo1qlu3bh999FFbWccwDMO0DrxGeOCUlpb27t07+bB3794lJSW7bUlEjuPceeed+uFFF100YMCAg7y667qmaXaKiNB1Xdd129uKFsGmtjpKqc5iquu6RNRZPlNSSqVUK/ZpGEanuPdDATvCA2enWeW9vC+JiIhqamr0w2g0evDvYKVU634MDh1s6qGgs5iqErS3IftGKUVEncVUpZQQohX7zFgvCHaEB0OvXr3Ky8uTD7dv354eIKYjpQyFQnfffXcrXt3zvFAo1Cneu47jdIp1F7CphwD9ld0pTBVCdJY1Qt/3eY2wFekEX6MdjR07djQ2NgI46aSTFi9erPfRrF+/ftu2baygYBiG6XSwI9wj5eXl119//d13393Y2Hj99dffcccd+vkZM2bMnj0bwJFHHnnppZeeccYZd91116xZs2688caCgoJ2NZlhGIbZb3hqdI9kZ2efcsopAK644goA+fn5+vk777zzqKOO0n8/9NBDzz333Nq1a3/3u9+dc8457WUqwzAMc8CwjrAtYB1hp1C8gU09BLCO8FDAOsLWpRN8jTIMwzDMoYMdIcMwDJPRsCNkGIZhMhp2hAzDMExGw46QYRiGyWjYETIMwzAZDTtChmEYJqNhR8gwDMNkNOwIGYZhmIyGHSHDMAyT0bAjZBiGYTIaTrrNMO1J3Me2euxoxI4mVEVRG0NdHK6P+niqTchA2ESXMLqGUZyNbtnonYcCiU6QaZRhOgPsCBmm7Wh0sKoCa6qwthLra7C5FtVR9M1Hjxz0zEVhFgrCOKoAtoH8tMzPMQ8xD/VxVEfxZRXKm1DSgG31ecXZOKoQw4oxojvG9kS//Pa7MYbpzLAjZJhDCAFfVuGTUiwpwxc7UNqAIUUY3g1DizDzaBzZFT1zIcWB9FxX31CPvC+rsKoSr3+J386HIkzqg8n9MP0I9OZokWFaDDtChml9ttRh/lf46CssKkF+CBN649je+PY4HF0E44Dc3q5IgX556JePrx0ZPLOtHgtL8NFXuHsBumfjlIE482gMK26dyzHMYQw7QoZpHTyFhdvw7ia8txkRF1P74/RBuONE9GirSnx983FhPi4cBkVYugP/WY9vv4aQifOH4oJh6JnbRmYwTKeDHSHDHBRRD+9vxpvr8cEWHNkVpwzE/TMxrBtaJfAj36NYRJgWABHKauFZUmBsT4ztiVumYEkZXliN05/E+F64ahSmHXGAM7EMcxjDjpBhDoS4j/c2Yc6X+GALRvfAGUfhl9NQnN2alyDP3XHXdV7VDmGakEaPm/5mduuzXz0IYFwvjOuF26bhtXX4w0L86gNcOxYXDUeYP/oMk4A/DQyzHyjCwm14aQ3mbsCI7pg1GL8+CQXhQ3ItikW8qu0gItcB4FWW7a8jTBI2cdFwXDQcn5Xin5/jL4vwjTG4ZjRy7Fa1mGE6J+wIGaZFbKzBC6vx4hoUhHH+MNx8Arof4sU/YdnCtMmNZ4+ZZh91THjo+IPv89jeOLY31lfjb59i6uP41lhcMxrZ1sF3zDCdGHaEDLM3Ii7mfIlnV2JzLc4disdmYUhRG12aSIEIAEkprNaM3Y4qxJ9Px8Ya/HEhTnwcPzgOl4xote2sDNPpYEfIMLtneTmeXoE56zCxD64fj5MGwGzjjIS+T74HIPr5+9HP3ze6dgsPGdeK3Q8swN/OwIpy/GY+Hv0Ct03DtP6t2D3DdBrYETJMM5pcvLoWTy5HbQxfH4l3rjzkU6B7Qthho2uxX1shDBNA0/xXY8sX+A21WaMnZ487sbWuMrI7nrkAb23Ebe9hSBF+OQ19OUMNk2GwI2SYgC+r8fDi8JsbMakPbj4BU/u3s9JAWHbPWx9UsSZhWg3vv9Dw1jP6+fiGZa3oCDWnDcSJR+Cfn+PsZ/Ctsbh+fJuHvwzTfrAjZDIdT2HuBsxehk01uGAwzb28w2jPiaqf/oNXullYlopFhTRgmOQ7ZlFPAJEX7o1s31xw6Y/sI4a2ytVsA9+bgFlDcNt7eHUd7joZY3u2SscM09FhR8hkLuVNeHoFnlyOIwtw9SicNgjRpnhebvtICshzIYSeBaV4VISyvKqy6JIPmzVSPgCvssyvq3K/+BBAdNl/W8sRavrl47FZeHUdrpuDWUNw0/GsOGQOf/g9zmQii8vw2Bf48CucPRj/Og+D22oj6J7wyreV//H7MK0eN9/f9Mlb9a8/bhR092srhB0i14GQIAKRME3yXZAqu/1yc8BwM5yVM/G0Q2HPOYMxtT9ufx9nPIU/nIpxvQ7FRRimo8COkMkg4j5eXYvHlqLJwVWjcefXkBfa91ltgLv9KxWLAIgtXxj/chkAv64SROTGQQD5uhl5HgAVjQCAZRd/57eHzqSCMP46A3M34PrXceEw/Og4WMahuxrDtCfsCJmMoLQB/1qOZ1ZiVHfcfAKmH9E6uUBbCyO3C4QAoeb5e7VkUAiT4EAYIB8CIACAFFAkDEmeEvahyWfTnNMH4dheuHUezvk3/nJ6+4fODHMo4J1hzGHOohJ89w3MfAoxDy9ehMdm4cQO5gUBkBsHkXZ3WjtIUPpI8p/UHwQAqqGu8aM55MR37qu1KcrGP8/CNaPx9Rcwe2nKFoY5bOCIkDk8iXl4eQ0eWwrHxzVjcM+pyOnAicTI99MeEABBRIl/0xsmG/hb19R+tVo11eefflkbWHjJCEzqg/83F+9vwd2noqillTAYphPAESFzuFHSgN99hBMewdub8POpePcqXDWqQ3tBADI7D0IIIQDAMAHAMABAGgQEh4QQwgAAywIAOwzAKOjWZkYO6IoXLsLQYsx8Cv/d2maXZZhDDkeEzOHDx1vx2FJ8UoILh+PlS9C/S3sb1GL8ugokgz/PBQA9Qep7AkgeIvIACDPU/Yd/iZlZWeQecD2KA8OU+MkJmNwPP34LFwzDD49j3T1zOMCOkOn0NLl4cTVmL4MArhmDP5/e+copGEW9hGkBRL4vLJtcB3YY8agwbXiuyMmFMOA6MqeLX1eRdczxVs8jYg0NZl73drF2cj+8fhl+9BYueQH3zkDvvHaxgmFaDXaETCdmYw2eWIaX1uC4vvjfE3F83/Y2aP8h3xOG6VeWkQ4EgWD/ixML5BNA3pRz8mdc0Y5G7kpRFh6bhQc/x9nP4Hcn47SB7W0QwxwE7AiZzodPmLcJs5diVSUuHYk3L0evDpIUbT+peuTX0RULCi7+vtVnEAxTCJDvC9Miz4EVghMVhk3KMwt7tLelu0EA143DhN648U18vBU/mwKbhYZM54QdIdOZqIri2ZV4Yhm65+Ca0Xj46M795Rv/cimUiq9fJrPz4HvBQqDrAIDrgECeA8CrrWxPK/fK2J544zL85B2c/yz+dgYGdG1vgxhm/2FHyHQOlmzH40sxbxNmHIV/noWR7bM61soUXnFzbPWnuSde4DfWAoCQICWkQcqXhd2zhow3uhT5kYbcyWe2t6V7Iz+EB87E7GU4/zncPg2zhrS3QQyzn7AjZDo0ERevrMUTyxBxcfkxuONEdOkYSdFahfCISeERkwB4laUAQAoAgQAIaXS96Hvtat3+cdUoTOiNG97AR1txx/TOt1+JyWR47zPTQfmyGre/j+MfwXubccsUvHc1vj3usPKCe0IEKorOl8JlWDHmXAoQznoaqyra2xqGaTEcETIdC9fHmxvw5DJsqsUlI/CfTrsRZr/QgnoICeVDSvhKWFkAmhbO9co2w7QhCJ4ns3P9+mqjoIdfvQNjT0Lu8IZ3nyU3nnfaZbp+U7uTbeHuU/HKWlzxMv7nWFw7tr0NYpgW0CE+PAwDYGs9nlqOZ1dhaDGuHo3TBmWQWNvuP7jnzx9u+uDlhvmvBrlGow1+Q03NM3/aTWspoZRZvi1+xhV1cx4FYPU6MmvM1Da2eS/MGoJxvfD9/+DDLbj7FOR2tNSuDNOcjPmmYToqukD81S/jnGfgKjx3IZ48DzOPziAvqDGLe4eGTxCmJXPyIQAhKh+8Q4RzIIQM58hwNoQIClNYIQhQXVXdKw8K0xKGaRR2uL1D/fLx3IUY1wtnPi3f2dyZt/YyGQBHhEy7UdaIZ1bgmZXom48rjsE/z0Yos78ww8Mm9P6/l6oe+lVs9Wd+TTlVbdfP504/F9Kof3N2QlkRB8Ev35pM1O1Vltn9O9xmTVPiB5MwtZ/6wVz7o1LcPh25dnvbxDC7gx0h09Yowgdb8NRyfFKKc4Zg9rkYwlXuEgjDzDn+DL+20ijo7teUG/kFKtKUNWYqhIitWKjcmLd9K+wQ4jFYNjwH0hAQZreghHzdnEcb33/RKOzh11YWXX1LeMRx7Xs7AMb2xIvnx/60OPv0J/H7UzC5X3sbxDC7wI6QaTvKm/DvlXh6BYqzcfkx+MuMjrvJ3q+vBoSRX9D2l84aNTlr1ORdny+85tbal/7pbf+KnDiIdFwI5REQ37zWLOqjGmpiKxaS53oV20CIrV3SERwhgGyT7vwaPtiCm97GyUfi1ikdvRgIk2nsUu+MSSMSifzzn//csGHDxIkTr7jiiqBKThpPPPFEaWmp/rtHjx7XXHPNbvupr6/v169fXV1dK9rW1NSUlZUlZSdYSaurb1hWm/fkcny8FWcNxuXHYETb1Q7aPxoaGvLy8tztW8rvvgFC9Lj5frNHhwhhokvnVz12pzAtcp0gK7dhwveEkEQEAWGFyIlZ3ftYRww1Crqruur80y/vCGuHSqloNJqTkwOgIY5fz8d/t+J3J2Na//a2bBccxyGiUKgTaHQikUgoFDKMzF5LaD04Itwb55xzjm3b55133j333LNy5cq77rprpwb3339/v379Bg4cCCAri2uV7kxVBM+txpPLcvJCuPwY/OFU5HSGVSLVUKO3bka++CB09Fi/ZkfoyJF7dyrujq/c0k0ytyvceHjYBOzym+kg8at3gChIzK2r+CofAJECAAK5MQB+Q13ekPFGcU+/uly2Rzi7d/JC+P0pmP8Vbn0XE/vgF1NRyB8apgPAEeEe+eSTT2bMmFFaWhoOh1etWjVp0qSSkpL8/Pz0Nscff/xtt902c+bMvXeVgRHhwhI8tRzvbcaMQThvUOSEgdntbVGL0BEhgMjn78fWfh5Z9JZOeGb26N/z1n/u6SzyvbKfX6JiTfph0bd+lTWyleckGz58pe7Fv0MIEAnDJN+DMEC+fgZA+iFhGOT7+adfnn/Gla1rxgGQHhEmibj440K8vAa3TMEFw9BB5BUcEWYsHfRrtCMwf/78KVOmhMNhAMOHD8/Pz1+yZMmuzV577bXf/va3r776qlKqzW3scNTH8egXOPkJ/GIexvXCf7+Bu0/FMd38fZ/ZoVDKr61UkUYk8ruIvf5eFEIKOwRAT55Hv/iwacGbyaOxVZ/UvfawX1d1MBZJ/ZUnpL6etgnaPoHUk0j9e2C/cCOfvlP/xuMUjx6Mtfsk28IvpuKxWZi9FJc8j7UHNTYMc7Dw1OgeKSsr69YttZbVvXv3srKyndqMHj26S5cukUjkpptueuCBB+bMmbPbEE0pFYvFrr32Wv3wW9/61ujRow/SvEgkQkQdJyJcWSmfXmW+vcmY1l/98gR3Qi8FAD4iEUSj0c7y01Wb6q77vOHVh4KnlA/AjzVGIpG9nJj3vXvcNZ81vXg/gMhn8yKfzVO9Bhrd+4Go5tHfkOu4jQ3Zs647YMPi9bUAoBQACqZG9Q8vCjyePqRSs6ZuY/3ebd4VVVdZ++Q9ADwzFJ5yzgFb26xPpaLR6K7r6wAG5uKps/HsGvPrL1hnH+V/b5yba7fnBJWOCH2/E/xui0Qivu+37sfKtm3TzFCPkKG33RJs2/Y8L/nQdV3b3nmB64EHHtB/3HTTTUcfffQ777xz2mmn7dqVlNIwjAkTJui/jzjiiIOffvE8LxQKtbsjjPuY86X413JRHRWXjlC3TFFFWQCabQp0HKdTTDchYapR3KvRNKFAyocVghuzBwzXt0CuU/f8vSraCN+X4Wy/qT484ricqecg1CM0ekrsnWdUtJF8D4YVe+0he+ixuV+70Oo/2Nm4kqrKIk/9Pv+C7+mdqPHVnza+/2L2cTOyxk7frSWRBW9Gv5ifd9plVr+j6p6716ssE0LAMMl3hW2Tlk+4Lgypp0aFNMh3YVpw4zBteHH/q7WRp+/uctH3ZU7+rv2rSEPds38FQPGozO3i11dnTzotfMxks7i3X1uRdcQQu5VeMqWUUmovb4Crx+DsIeoPC42Zz5k/mKQuHk5GO02VCiE6y9So7/utPjXa7l8m7Qg7wj3Su3fvRYsW6b+VUqWlpX369NlT44KCgqFDh27evHlPDSzL+s53vtOK5hmGYRhGO753v6rDv5bj+VUY1QM/PA7Tj4AUuzdGm9rG5h0Y2lS3roKSv4HcWI+fPWR176sfxTesjX42L/0U96t1+SeeB8DoUtjz9tmN/51T9+IDUPH4huXxTau6nHxR9+/d7WxZW/7nHwAIDz02d8pZAJree8HZsFw11OQe+7XdWtI490m/oSaSlZ1z/Mzo5+8Hz+rNMsmChUhsnAFIB4ieA4C8OAju1nXuVmSNPC5n0um79h9fszi2/OP0Z1RdVe6EU3r+7EHyXGGH92fY9oYQYp9vgG65uOsUrKzA/34o/7UcP5+Kqe2xp9QwDCLqFO9VI0F7G3KYwI5wj5x99tk/+clPSkpK+vTp8/bbb2dnZ48fPx7A2rVrY7HY6NGjHccRQliWBWDjxo1Lly495phj2tvqQw4BH2zB40uxdDsuHI6XL0H/Lu1tU2tjFPUSVghKgXyRk28V9ax77eGmBW8aXYr9xmph2eQrQEnDVJ4nQ+HSWy80Crp7dVUyK4ecGAxTSEm+J7NzS39+sVHYw6+pEHaYfK/hrScji+YW3/B/RtdiIaVZEOxE9WsrKu67RZhWt+/9XgdwOSfMjHw2L3vCKUZxT2GFoHwQJSLCMOIxWBZ5npASShEgDEmeL0IhOHGYNnmOkCYRmUW9dro7cp2K+37qVW0XhgkpyPelaZPnkBsr/fnFXS/4n+xxJ7bxgGtGdMO/L8DcDfjl++iXj1smY3hHldkwhxnsCPfIEUccccMNN0yePHnKlClvvfXWn/70Jz2B/sADD5SUlDz77LNbtmyZOnXqxIkTLct69913r7vuuuOPP769rT6ENDl4bjUeX4osE9eMxt9nInyYvn38qjJy4/pvaqh1SjZEl3yoIo16+0wSpRwAqqGWiFSsEQS/KdgYTHqprrEeICptSu7N9utr/PoaZ/0yv7aclHKry/3aCqNrN2fzGq+iBED8y6XhEZNUQ63e80lOPLrs46QxgWQiHiNScOJILgom/qB4DERwYgBIOQDc0o12v6NFKCVT8CpLnc2rE7cKAMqNgeDX1YBUbMWC9nKEmtMH4eQj8fQKXP0Kju+LHx3HVe+ZQw7LJ/bBkiVLNmzYMH78+COPPFI/U1JS4jiOfrhu3bo1a9YIIUaOHJlssCudXT6xpQ6PfYEX12BKP3xjDI7tvX+nJzUJHR9tKrlO3Sv/JNch11GNdbF1S6w+g4zC7vEvl1GsCVImFAsSypeWrVwHpg3PFYaE8olAhiF8H5aNpP5dGiAlANJl6ENZFIvIcI6KNXU5+9rcqefUvvwPv6Y8tmaxDOeoaGPWyOMKr/7Z9ju/5ddWCAjSm2IMA74nrBC58UBEkTBGGCZ5bnBIR4SGQYqEECIrp+fPHkquFKqm+rI7riTXAUGYRnjIsV5dhbttg7Yzd9qsrud/txWHdLfyiZYQcfHIF3hkCU4ZiO9PRN/dLHS2MiyfyFgO05/0rcfYsWPHjm1WVC19pXDw4MGDBw9uc6PajoXb8PASLC7D10e2qDSgu22DijaGjj7YPbHti7DsrhcG1eGrZ/8OgIo2dLv87rKfXwwkt2sGBeWV7wGA8gCixIqd8H0AwvMICFTwOmJDEC1qfYJyYgCcTavifQcVXHRj/dwnY6s/o1gTAKd0c3TpfL+uEkSUlEIoDwD8VIdJY4JFTc8DQL6LxOZSIlBTvd9Ym3KEkQZyHe0+yfPyZlxe/8ZsFxsCC2P7t9H00JFt4XsTcNUoPPg5znoaZxyFGya0hTtkMhB2hMxu8BTmrMODSxDzcO1Y3HtGi2ZBvartO/74fSi/6NpfZh1zwqE3sy3oMus6s9eA8NBjZTi76Nt3xFZ/1vjBS8ExARCEFKSQJuBLydt1iV1ICd8XQgZZYAIk4AshCIiuWhRdsaDwsh9Ly0YQMvqqvqr6X3dDGKneAAgJUhASUJS8VpoxJAX8RPu0s6SV2vwirJAQksjPnnhqeMhYu9/RXS+8IbL4PbO4l1+1Pfu43eysaUfyQ/jx8bh2LB5agrOfwclH4n+OxcAOlzOH6dywI2Sa0eTgqRV45AsM6IqbjseJA/ad9cMt2xz9Yr5Z2NMp26i/eqMrFlAskj3hlLaw+BBjdCnKP/VS/Xd46HijS1Hjhy8Fzi6I8CTg7zRM+lDzVYfEI50CRoL8xFNEAGJrPifP2aV187N0t4GgPnmQABFMn6au3+zUZuYJASmhfCGCONIs6pl/2qX7NSxtTNcwbjoe143D40tx4fOY2Bv/cyxG9Whvs5jDBXaETEBVBI98gadWYGp/PHgWRrY4XXPN039yvlqbij+AyKK3I4vetvoeZfUacIisbS9UtCnNRxEAIh+A8FUi0QsABEvvet5SEQBFJHQamGaHUjFi5PP3Ev2mHQpSiSa6TX9SNXN7iaSjfqoBUmepeDS5mmR0Kep+833RJR/W/+dfTYvetnoPsPt1jun9/BBunIhrx+LfK/Gd19G/C64f36Lfagyzd9gRMihtwAOL8cpanDMEr34d/Vq8DOOWbKx/c7aKRwEI0yYvDmEK8iENkZVr5BceQqPbg4a3n4lvWCYMi8gXRCQN+J4wbXJisCx4rp60FDD9jJQAACAASURBVAowDfI9WCYcR5gWeXEpDVI+hBQQRH5QR8K0yY1BmkL5JCCEIN8XpkmuK0yLHF+YFvkeICAARcI0yPOEYZLvw7Sgd8T4SghAGuR70rCVigvTosAYApEw7bpXHtRFCnNPmBkeMcnq0V8NHoO3nhKGWf/646HBY/O+dmF7j25LybbwjTG4chTmrMM9C/Cb+bh2LM4fetjuYWbaAH7vZDRf1eFvn+KtDbh0JOZdiaL9zIzd+MFL0RULdZZLLeIGeQR0PefanONn6vSbhw0q0lj3+mPJhwRAb5Nx4wDIc0CJjTAINq3AcQHAc0CJvGgUxHFKz4J6cQDwXUIqVxq5ibOSG20Sx4IdMekNEjtitDEqOCtlDABy47HVn+m5VL+2MjxiEgC/ageUIuXE1iyOrf08d8pZrSiibwNMiXOH4tyhWLANjyzBPQtwyXBcOQq9O8f2ZKZjwY4wQ9lSh3s/wbubcNUofHANuhyQz8oaPTm29nNIU9WVCyus3LjZtRssOzxiUufygk2fvF3/+mM5x58hJs8CoBprKx74BblxuI7Myffrq83Cnl71dpmVq+JRoSMtEKRJviusENwYrDC5jjAMKEVEwjDI86RlkxeHFUagdvAhhJAydcjOghOThkW+ByEgQEoJ04brwA6LeAyWBd8jIQASBEgTnivsENwYGSH4cSFNEBGRkAYpT1ohcmOwQuQ6kCZIASSEQb4nrBC8mIo2lt1+hczNV5FGYZqAIN83C7p1Li+YzvF9cXxfbKnD40sx8ykc1xdXj8ZxfXm+lNkPWEfYFnQoHWFpA/7yCd7egKtH45tjkHfQDmvH3f/jlmzUezdyJp9ZcNGNKtYkDIucmMzK8ZvqI2Tk5eeT55Ibl1nNFRhKqUiDyMqheFRmt9uP+coHfh5bs9gs7JF93Z153XrEls6vmv1/zVpIiT1VFwl2cu6u3IPe4SJ2+ykTwJ4O6V4l7eGKezmU2C+659oTaUu56fT5/cvCtFWkQea2cqKgA9YRHgBNLl5cjSeWwSdcNQrnD92/tzfrCDMWjggziKoo/vYJXlqDK0bh/auR30qf9/wZVzZ9/Ia7dZ3fWG90KXa+Wltx780wLIpHZG4X1VBrjz8556Ibdtx1nWqoLf7u70JHpRLRVT54e2z1pzI7T8Uixdf9b3jo+NaxaT/JO+USSOnXVdffdW1jdr6KNQkpQYJICdMkzw0WAs0QPCehYQ/CPmFZ5MRhhuDGhTSIlAAgJClfmrbSKbDduDBMKJ8ghBTk+8KySMvw3bgwTfJ9QAghSfnCtMhzhGFRYrVPSAMg0uUGPRemBScOy4LrQSYWAqUO+2xy9BUTgnoQGSY8T1q2cuNBA8MUyiNIIQUp38grFFao8h+/iK1Z3PXc63JPPL9dXoWDJ8fClaNw5SgsKsG/luEPCzDjKFx+DEbz/lJmr7AjzAgiLh5agkeW4LyhePcqFLVqWfCsY47PGjGx5KfnAuTv2BrzXXIdnRJaNdUB8Laujy1f4NdWAoiu+lTm5CV3k7rb1gNQ0UYQuaWb2sAR+g01bumm8NGjIQ1n6zphWKqp3uhanDvt3Jon7wagovVIEyIE4nS9pOfHgYSSPbFiR2mJsKm5al6lrfPpkveJTabBQmBK+U4EkN75qa+ldfrBuckrBsbolUIPoJQxae3hpQnqkw+1MUGqbk9vXQ1SwTXVR1d+4mxdD8Ap2dAaw9zOTOqDSX1QFcGzq3Djm8i1cdkxOHcIcneuH8MwAE+Ntg3tODWqCM+vxh8XYGIf3HzCfuwI3T+ISn9+sYo0aNl4zqTT/Mba2MpPYBjw/SDjV3JCT8qeP/2H2aMfgLJff8OvKgsfPdoePCZv2rnpKTEPEdt/802vsjTv5IvDIyZW/PUmPbEZBF7JXGjauwQTm5ISDVKHNPqhacLzgr/1NGniXEgTyoNhwvfSZkFFEE3qDaKet9O8qx6oZCxIKlWGPhjDxBVJ+aK51l4YFvluIvuaCCQWzYrXm5RuTNohq99RWcMm5JxwptG1uBUHvC2nRndvAOG/W/H0Cnz0FU4bhK+P2GOOQJ4azVg4IjycWVyGX30AS+KBMzGm5yG+mJRI7G4MjzjOLd0YW/mJgKBkQJP8yUWqcdHcrGHHho4eIwwDgLBCMpQN2RafalIeAHfHVnJiKat0JJeu0ksconRtfJrzAAAooJmOPe1c3ZCSysHUD06dN5RSzXZatKO0/xK7RZvLEwM5f7OzgqtApZ2V7JFS5+5u8TChQUT+zKt3PdrZkQJT+2Nqf1RF8eJq/PRdALhkBM4fiuL93CbNHK5wRNgWtH1EWBnB7z7Cx9twy2ScM6QtdtB5lWVu6SbZpZCiTeEh40j5sVWf1L/1b3fr2t1uJxGG2ft3z6tIY2z14ppn/wyitlmd8qvLY2s+q3nuXhDlTj+XYtGmRXODCMkwoXdv7vqhECbIa569JYGOBZPhV+IEgIJQL7j95t0G+WV2t+0lONQsFmzWrSHh79JhsPvGINr1rFS3iaB2pxdDgpTVa0CPnz6wj+Hbf9o9ItyVxWV4ZiXmrsdxfXHxcJw4AKYEOCLMYDgiPNwg4OkVuGcBLhyGd65EjrXvU1oFs7iXWdwLgIo11Tx3r5BSRSM6PbQwTPL0lKMuvyCglAhnC9OKb1wRX/uZsEMUj4ndFVJvdYzC7lnjpte9MVtF6sPDJng7tkIIGCb0PKTv6X8hJQiAEoZJnidMg1wPpgnfCyqZq+Rko0HKhzShXCENKKJg5tOT0lTKEaZJriOEJPgCgoSE8vW2FzIsqEQdCSFSE5WeK0yTHF/PoALajamEhSb5jpCJ6hM64DYM+B5MA64Pw4LnCGmAfCIR1KzQOn1trSGbvRamQa4S4X2lVD9cGN8L43vhV9Px+jr8fTFunYfzh+Ki4eifKQPA7Aw7wsOKTbX46TvwFJ4+H0OK2seG6BcfNX38RvBAa+11tQTfh97aTwRANdUrJ177wv2qqV63VXVVbWOhDOf0/MUjFI8aXYrq1i8DUWI/S9qulp2qOgS7VAJ5ezBDqVvqJ/2ddrVoebveR5M6RKBAdK9/InguJfshSlSEcNP+9QKj9SF/5xITqTXLYLOMbpDauQNQcMjV/yZfiyBBXPJaqrH24Ma1k5Fj4eIRuHgENtbguVW47EX0zrPOH+KfN6wVNEVM54KnRtuCNpgaVYRHvsB9n+L/TcJVoyDbUE7c+NGcxg9eyjv54uzxJ1U9+mu/crtbVSakgOfDtslxhG3DcWAG2zQgJXm+zMqROfnkxlVdFUybfM8q7iXzC4u++UuZ3Ra/zP36mqpHf62a6r3KMh20STtLOVFh2uS5Qi95ktIKB2mHlRMTlk2ep1OX6RRrwneFHVZOXNq20ooFUoIQ3KNtKycu7RA5DgL5hN7wopUVjrRD5MTItKFcAQkhAvmE6wRXNG3yPCGDbKI6WEwzxhVSQgFCQVrwXNghcuLCsslzIE34SgiCYcDzhG0rJy6sMAVaDkUCEALKl+Ec8r3cabO6nHlNq49zB5wa3S0+4d313vNr5IISecqRuGg4juvbpp+j/YKnRlsXjggPB0ob8MO3oAivXIL+raqHJtcRhonkSiQRuQ4MQ4cvwjDIc5sWvOFVlDR9/KbZvW9s1adBQx2NxGMAyImDKBAYIAhHVKRBRRogJIh0ljK3fBvKtzlbVoeHTaB4VISy9L+teT/atnhUWKHYus+dTauCZxwfgHKiINLl4MlPLN05MQDKjYOIHF0pPhFOKZ+Cu1PKiYGC7Tape3TiIFLxOEBIVJbQgZquRKicWPL29T6XYLgA0lcMjElYrpzUoaBCfcJOLe1wYiAiNwYCdGNK1bUHQE4USTVIAhVp6PP7l4PkMkoFM64AfF9YNjmxNtjN2+4YAiceoab395tU6JW1+N8P0ejgwuG4eDinbTv8YUfY6Zm7AT+bh2+NxfXjW/kHbPzLLyr/cZtR2KPHzfcLywZR+R+/75RskOEseD4pX4SzVVO9zM4H4FeVVPztZmFaUD4IkIJ8BcuGVpR7QY4xIQQJiYSiPPieNS3yXQgppGEW9WyY93zdaw+bXbt5NeVdzvpG3imXtOJNadm4zMmnWJOQUgkhfCUsm1wdLUVFkPBMQteL0PJ2y6Z4TFg2PJeEIaCIIAyZFNQLM0SeTnimCEio5m1y4sK2yXFgmlC+gM6O7eqIUFihxO17EHoemci0kMjHLUwbrgdDEAiKhGGR75BlI66DRReGhAKghDRJudIKKSfWzBhCsLJoh8iJCTtMbgyGCd8XENCC+vwiYYUAkOvs+P13/dpyIU0IQa4jc/L8+prs8ScVXvnTVnwVOjKFWfjGGHxjDFaU47lVOPNpDO+Gi4djxlEIcQB2mMKOsBPjKdz1Ed7eiEfOOSS5M5yt68lzvfJtsdWf2kcMdbdvcUo2QCkVadINqLEOAEUbAPiRRhClBSgAIFyHkMg6rVe2iLTqIFB2JxfnCCBFSnk1Fc7m1SDy66oAxDetbq2f4+S5zldrnY2rQKQag2lq/ctBB17w4qCkMYmwT6/wuWlqdPICIYKndjqUUM0nqielzqXgThGsPqr0bvVSYnKVQuciCAbNSQ4mAPIdEOAkMmsjCD2RWDJM5PLWab4TxvgqeY/kOqDEKiNI9+w31MbWfRE6cphqqvcqSgAQ9Goo/PoaAMnQOaMY2R0ju+PnUzF3A55didvfx6whuGQEhndrb8uY1oYdYWelOip+9KbMD+H1S1stWdpOyJx8AELKqkd+HUxUmiYpJbQ+Dokt/lokYBhI14ZrzYDeyhgc0pJzXTM2ITaXBlSiersOl/IKupz9TaOgu1nUw6vakTv5zNa6nZqn/xhZ/J6wbAA7G6OF/4ZBSgkYhDTVvCHh+3rLK7QKHgkZRaBhN8nTGnY3VYZe35eU5CshTR3vJlSGSUG9HhmVUFkAkKDgoRAGQW8TTVc7mIAHw4Tn7DKeAkq/IoqkhA6+07X2qT2xqSsKEgSClJV/vzU8dHzxd35bcNmPvfJtwjCdkg2xFQuFHc6ZdFrWmKmt9Sp0OmwDZw/G2YNR2oBnV+Fbr6EwC18fyXlqDivYEXZK1lbhG69mnT+UfnyCOITL+X4yhkuEbsk1sGDLoQISlYVUWr1ZJEXcaXVlVfJv/d2dKiSbphNXkcXvhQaOMIt6hoaMze3R/2BvgSjy2bvCCvmNdV5FKRCEUEIbrfNTA0IRAUo/h2bCvsCZBBaqoPQ7pQ4lavD6iXvQGvrUfVHzMrmJ8Uv9m7gEdKwcDB12o4IX8Ck1dMkEBekdpjT+afvgUoea/xv0K5RPgFezo3H+q2ZBMYp7ZU84pfHDV2IrFoJU/pnXyPBhpTyPrfpUNdRCQISy/IZau/9gu/++SxP3zsMPJuH7EzH/K/x7JX7/X5w+CJeOxLhebWAyc2hhR9j5WLANN7yJW49zLhhhiUOplc85bobMyZO5Xf3q8vq5T3mVJc2+c5N/pHkFLXfbWa+9c06TRMOUOj3VuOHdZxvmCRCZ3fr0/PnDB3kL0aUfVT95T0JLLpNXSjmJwMuluYrmBLcVaD4Q+Dl9SAAU+FRK1IlPuHk9Ago7j0XysikXSDsdSczXAjsL+KnZUCN9BHdxr+kZcPRNiuTtp+fCST7yK8tqX7hfn0WemzttltGlyOrR7zDzgl5FSeWDv0xPEiRCWb3vfE4YLfoylALTj8D0I1AVwfOr8eO3ETJw2Uict5+VLpgOxX4X8WHal7c24oY3cf9MzBzo7bv1QSJl1uipMrdLfP2y4MtZmkCgDoQQQidFM9L+FSL4HpcGAKkbSBOAMAxdck8rEyAkgKAHaUAIoRXlySd9r+bpP7olGw/qDvILA708IK0wAGFagTEAoK0VwZdgcHeGvrngNne6BQhIGYjfhWx+CBAyOTgAIC0AMGTQoX5ept24zjAXnCWE1P8aaSMjCXpsZLIrJK8FkbBEwNRnSQDCSI2wHobkkyJ5dSEgEm2CG0ndggxlCcPMHnei1WfQwYx/RyOyeF79m0+kkvkJCUDaIbH/6f2KsnH9eMy7CrdPx6ISTH4Ut7yLlRWtay/TRnBE2Jl4cz1uew+zZ2FkdzQ1tdFFG+Y+Gfn8g+C7UgXbOvS/QSWF9JIIyalR5ROg0tXoyW0dekI1TeWd0nfrBr4HwKut9Ba95TfUFl/3vwdsfGjgiF63PS5s22+qN/OLvNqK8j//MM2YRICkxenBLaRNCCNRhj7Qyze/x+D208o+pHKNqtRZWsmenBlO07AHm1aSMnyVuv2Eat4TgTGUGig/ZWcqOvdSh8h3CRAqpbpI3mPQIJU6XO3SrQ/AbzgcxfVK1Tz1x+QeIiB4l/pN9eR7+hfS/iISlYErI/j3Snz7NfTIxdWjMPNo2LzFtPPAjrDTMG8TbnsPT5yHYXutDRD5bF7DvOdyp5+bM+n0A7kMUc1z9zpb10vb1lNk5MSEENBZ0CxdR8IgnyAI0oTvCjtM8ZiwQ+TG9b58CIjgUIjicVghXXUPSkGLzX1PmDa5jgiF4URh2kGdP0hSnrAsuK7IyVNNDeFhxx7YcCUxCrs7W9bUPn+/zOvq11Ua4WwvHhOWpe2EEOQrYVnkODIUIicG04LvkpAgAfKFZUPrHALFgqOrA4IgpKE8R4RCFItJO6R0GXrlA4FiQVoh5cRlKKQcfUihmbLCEXaI4lGt0xdCBAnPLEsfghOD1kjoooNKCVOr5sMUSwj/DRmszkqDPEe/FoGIwjApWbPC94QVIicurbByY8Kw4PskksZoGX6I4lFYtvB8s7D7QQ576+KWba555s9Wn4EFF92IA14Wl9Io6OZVbYdhQSlh2yKURZGG0FGjDswLplOcjRsm4DvHYt4mzF6K38zH10fiylHo0dETCTAAO8LOwpLtuOkdPHL2PrwggMb5r7qlmxo/fOXAHKHfWJtKkJaOEweSIm4diyQk204MoKCYQxAYJaTf8RgAuHEi0joEIKHv1rv50xTl8P1Aq+44AKQQff/4OgAo1Wy+cX9RKvLZPGfrumC1TgiAAklDcrXPiSMlb9dicz/9ELlxIClvT2okfABaL68F8okcbEH8p9w4EAjq0w41vyISIorkqmXiipQamYTW3nUACD3g2hgvFYInXwvlxna1kwIJf5qgnpLGxAD9EgOuQ4BXtf1AhvoQQRT9Yr6zZY2zZU3+jCuN/IID7Ecpr3oHKEhu0PXs7+a03p5kjSFw6kCcOhAba/DoUpz2L0w/At8ai1FcGbhjw46wE1DWiO+8jntOaVEpJaNLESDMLgdYUs7I7Zo75Sxnyxq3bAsplcgBraXfUdhhuA6kIZQiHRF6rrRDKh4XdojcmDBM8hUEpDSU7worrEMNOHGYFpTOWC1I+bBspIdErgspIYXwfZgWua7RtTuUKv/zD92yjcLOgpDdf/hns2j/qkm527dU/PXHgIRAQt4eonhcmqbSoZuQpBQsC44Op6IJ1bwEIEhBR646IrQscj1hSBCRzsftukHG8EA1bwhFFOgxvEAvb4fIjQtp6vKBJAU8XwTJ58IUjwUV6qUQEJSMCE2bnBgsG54HIYWArn1IrgsrhHgMlgXPS9avEIYkzw+uqIfdMIl8EKRhKt8JntTGGKZSvoSOQYOIELbW6VukfLOoo3xze9U7yv/4/3RBR5mbb+QchKxUSrOgh1ddZvUeKHPywyOPaz0zd2ZgAX59In5yPJ5Zie++gd55+PY4nHJkx83ZluHwZpmOjqfw3dfxzTH42pEtau/XVwPk1VUB8BtqvIoSr6rMb3k+ayHyz7gqe/JZ5LlQPkgFlc29ZAYvBd8l8qEUPAcg5cQBghsPVPOkoJTyXBDITcYuBM+BUlA++V4i8KKUylsXW/c8oiBc82sr4htWOFvXkeuqpnrVWHsAG2fcr9apSKOK1IOCQJOcOEDKc6FUkE6MFBwnuAWAXIeIoHwonyhhvOMARJ4DKPI9Uj4UBQmsU8EiwfNI+SAFz01lQdMZ0XwXpEj58LxUSOokgkVS8PXIKAqedADAdUAKyiNfj4ybvAV4DihhPykKuo0nG5DvQimQCrT5TsJOIvJcoRQpH74HokRMn1D3K+VVd5RdH27pJtVYq6KNROQ31qto465tvPJtyQwJe0Mpv7YChNCA4d3+5y5yHb++uvUtTiMvhG+Pw4fX4JrRuO9TnPwEnl4Bx9/3iUwbwxFhR+cPC1CUjevGt7S9zMoGILNyVWPdjt9eq+JRAMK0etz6oFm475/55Do77rreb6gRQgYFZHWBdWmScoKqQFIEWjsD8IOyQSQN+EnVPAJtuGFBi809NyiVp3ddahm+7+tutZ49CBZJaa29ikUq7vsJTAueGx52rNX3qPCIifs7elljpuVt3+Ju2xBbt0Rr2HVKay08hwAgQCohbzehnCBLABKyeV2kUJc3kgZ8rWEP1ghJ+TAMKCUMizw3pWHXgnozobXX63zpqQakAd8jw9T1koLdK1oUr6syBd0a5Pspnb4W/psmuTqnts4ArkCJUdX1pPTtSKHlhIAElDZGGobSeQ+CfT3pde0t8uKhQSOtPoNyjpuxv0N9iDC6FOqAOGvMtNDgMTK3604Noks/qnr0NzI7r+cvH5Phva7ICSGy86ihRubkxdcvr7jvJ8Kye/7sYaPrAU6ftBBD4MyjcebRWFSCBxbjTwtx7VhcMartSqQx+4QdYYdm6Q48vxr/uXx/1IKBsN1XTkzFo8EeRdeJfjbPHjDcq94eHjLWKNjjVgjyHBVpQGJvJ5DYUqjXmfSTyQq0uomemgvk6IFSGyJtl2Mgw09s1AwK1qcE9cG5oGR9IyDYcqn3ZNoDj8k/9UAyjgrLtgcM82oqkmYEa2n6EgkRXXDIb1ahnppt1NTtm8koE6OhUuOTvHBayfvAyaUK8KauopXsqbx0wRDqc1NZCJKvRbP26cOYHNXgiolXITBVJW9BqZTNQOJl0htllQfAKOrV9fzvtmhw2wSKRnTGVLN7X6OwZ9OiuWZRL6+yzCjsoRqqs8ZM8xtrAahYpGnhW1kjJprd+rjbNrhlm7PGTA2yCKX6SiS681zVUKMzyEc+e9fqP9Sv3h4eOh7Zh7Yi5qQ+mNQHqyvx988w9TFcMxrfGM3qww4BO8KOiyL84j38bAqK9if1f8FlP44uX5A1clKzgukCdW88riMPu//g7j/66x7PT+rnUs+Q3mKiFciJPSaBZhsIkrMELZpr7YPWzc5NQAKByFt30cxapHTmaZfYf6LLP6565NfBppj0bmmnK1LKKQIAsieeDkGRRW8FmmuRyqezE0mviFQHYvcqet2C9BbQhEm7INJk9Lv0oYPRxNahXYvX6yA3dSRlTCIxXtpQJHx9YjA64vpVaPCYom/8Irr60/r//CtIPmdayQi7S1117vRzpRWKLPtv3cv/aPzwpZ4/e7j83psoHs2vKsufcUWzvqTs9r3/c75alz3+pKBMClHdnEeDz8WRI7p+93dtcEfDivHXGdhUi/s+xbTHcc1ofHMMu8N2hh1hx+W1dTAEzh3a0vZ+bWXDe88bXYr86vKIE/UqSvREWULkrmcCoWKR2hfuz51+rlnce9dOhGHBNOG5Kb+l5wOlAT1Hl+gn4eIIQgJ+MDWXdKJCQOkJwLQ9n5RyiEEeThgEX0hBfmJTaDCV5wezrFLAh7QP8HtCWGEtZSd9RaXTbPpCBknWtNcRpp3QD0SEYZHnhIeMBiGy6C1hGOSp4PalRXrulBSI9ESoLj2PYGZYQEl9eyCl55B11tDgGSGFEKRIGIJ8JOaHZUJ0IUiRvuWEJF8iyDUKgIKHElAQQmitfWIyNjHhrEDC0C1ACbl9wpjEy2SA/ECSTzqvqSdMgxzPyC8k32t4+xkon5y41Wdg9oRTDmzwW4us0VMoHo0snCtMkxwH0gD0uxrOhmX1kQb4LkWbAJBSdS/9Q48MdpcpxuozSKcIEKHsxBuDElP9bfo74MiuuOdUbKnDXxdh+mx8eyyuGYMs/j5uJ3jgOygE/O1T3D5tPz6dDe/8u/Gj11IigWbBWWoC0KsobSzfpprqC6+6ZTfXdWKB5iEZjaSprVO11DUqTY7tNT+k/wjOaj4dF0x/6kO7TDwiMTWqUvpu1dTQ4mFohmqsSUrjA+PTZmsBEKjg6z/IGjHJq9phFvWs37Yxr88A1VCjvy6tXkfUvT47tmqRvpHQoBFdzr5WZOVGFrxZ/86/g5nPtG7T8gmkjYxK09pTMP2bfuNpgvrUITSbUE3eQtr8p5+WpjXZPjAmEP4TIJISfj+YcE5p7ZNvDN8DYHTtVnj5TXb/IdEVC+v/86+gWyHCwyfq9OvtSPbEU63eA438Qq96R/Vjv/WcmL7f6MpPsPKTZDOqr27875wgyd3uttUkUQ3VqTeGzkUQb6sUFWkc0QV/OA0ba/CHBTjxcfy/Sbh4OEzewtjm8JB3UD76CqbElJYlnfbrqyv/cVt88ypACDsEQNohCAjDgjCENGCaQghh2gB0A6NL0a79NH40p/KhX4lQNqQUhimEASGkaQOQ4RwIYXTtJqQpDFNICSGlYWlZQqJbIQxTCCmkhGECArYNAJYNAWFa0IdMExDCCkFA2BYAYdpB7jFpQEhh2hCAFYIATBtCyC5FXlVZxf231j73t+bzgfvAKOgupSEMSwghrRAQdCtz8oQdkuEso0tRePgkmVdgDxgq87oafY828guTecWsPoPCQ8dBCKOgB4QIDRlv9T3KLOoZGj5R2CGZk4dk5jYrJHQuNyEhpDCt4B6DBkKYFoQQQgr9WuhBM20AMC0IAWnAMCGCkZF6fEwLUkAaQRY6ywIgrWDYhR5waUBIWGmvhWULIWBYUkgICW2Mfh3tsAheC0NIQ0hLiMBOIlX78oPxjSuMgu7CtGAYEEKEsisfur3xv3NaPuYtp+Gdf1f89cfO5tUtaWz1HeSUbqx9PNUAMQAAIABJREFU5UEyjOQbI3grysR7O/g3JCB2+w6vn/tk+V9+XPng7Y0fvS6lIUxLCCFtGwB5Tu3fb/G2tMiY1mVgAe6biYfOxpx1OP1JzNvU9iZkOhwRdlCeX41LR7S0cWzFwtjqRGl4rdTW5ch1Vi0CFAhAam89vNrd7I9vePvppNAiWYQhKHFH1Of3rwjLjq1bUnn/rcEhPykbD0TZiZARwQaNQKMdJ0rUr6BEQBOclVZaL/kL3U3WYU8U56upiH7xUXzdkvi6JbknXWAWtzThv1e1nVQznb6u3h4eemzBZT+GzvMp9/ZzMHfarJzjzxCWVhMGmy9CA0f0vvN5XdcpuH03BiRCMSRLFWrVfEpQTyBoCbyb1OknsxAk4sLkIUpUQEyq+5NVDJOHkgnD3LRR9eKgIPgDgHRj4inhP1GiZ32ocrtfUdr00ZyssdNS8v9Yk7NptV9dnjv5rBaOecupn/skuU7jx28UDhjWkvaN819zNq2ElMk3RlrSAAfJt6IbB6B3SDVDqfq5T6btWkpmIYgD8CpKUV4iFv4nZ/CYg72xA+KY7njqfLy3Gb+Zj0e/wO3TcVRhuxiSibAj7Ih4CvM24bbd1YCLfP5+zTN/zjrmhND5NySfNIt7wTAhBTxPWGG4MWGHlRMXpkm6KrqQpHxpWuQ6sEPkxMyuu6kumjttVmTRu35jlYpFzG59RThLeJ7IzlUNtVljp2k3EBowLDxsgl9d7lZsk5ZtdO1GvudXlSGpDdeF7qQkz5NWiFydYs3RsnEBkBAgJUwbblwbI0wbumIfQMFuCEdaOuFZiHzHKOoROnJEdOl8s7h3S0QgqZEp6gnDEgLke8IMwYsbhT2FHcqZdFoLqw0AEJZd+9IDTR+/YRR0V/U1RdfeFjp6jDAto2sxhAhyoekbMSwiAgU1CPVrAStEiQxzREJISb4r7BCcOEJhisWEZZHvi1S+t2BkEI8JKwTPISGFlrIEr2BYxKOkR9UwgrwHlkmuFxijh11aUAqCYEh4nrDDcPQbQ+c98HWObyIlTZvcuC5hH9+4PLb2MximkNIo6mnkF6r66uwJp7Z8zFuOUdjTK99mFgRvxdiaxdWP/dboUuhVl5vFfbyqUiO/SEXqYVpCSIrHRCgEIYIEcjrbnzCCEhymQZ4rQmHEY8KyletGFr8X/exdUkpm5fgNtWZRT6+y1Ajn+NFGYQZpH4SQOhMeuXHYYXLi7pfLSn9xSbfv/Nbqe9ShuOV9ctIATO2PJ5bh4udxwTD84DhWWbQF7Ag7IsvL0TcfxbtUv/Gry6MrFpITiy7/rzl1FvoFn1Wvajt8T/+4TyU8C5TpgQgAQWgCOHEQedXbveodOzmVvJMvzpl0eukvLgGQPWZq/hlX7mqbsMPF1/+68cNXal/8u4pHu33zF9VP3EVEiMeScQ8SK1JpWvtAQp7cAJpK6xWI1pFQYyRiF9cBEdwYAG/7lvDwSXvb7LoHvOod/5+9L4+zo6j2/56q7r7L7DPZA4GEJSEJYU0CYd+EIGAElE1A3gOe+FRQ3H0IKCKC2xM3RHwCCvwABTcWWRTZCfu+EyDbTGZf7tLdVef3R1Uv984kmZmEgDDn82GY3OruqjpV03VP1fl+v3FgZII28ryJX/nlSJ9TevYhDvywbTmA0ktPZLbZEYDq6QAz/HLU/TTFWhx9Rqj5oJJirVwCQIZ9LRkmIPIMGc8YL8UZwH6al64ETijWIroAU6MJTy2PWhT3FMH2AhsRRshuncLaqx6LMWeFxo9+Kjtz55H6arjGrDpXg3XYvlJ1tUHI0nMP61JBlwoAgtY3oXXYvrLiltIAoolhyQoQB8RRbGemE0P3ddneFfoABKvfBLMKgoqxMH8XQQlsyCJY93UCKL/2THoh5DBQna3OhM3eKVdUmiNwyo44YltceB8OvBrn74sPzdg0NX9wbeyM8L1oz7Zhx0FhT+mFR1d9++TSMw8AAFHvj8/svt4uDLmd9qnd87DMVtsDINcBQI4DGL0eiqV/hDRFLoDS84+u/vYni88+VFULZXIiVwNArJPRUTa0gEBuRtY1yVwdALgurHgQAZFgkOEytspHjs1gNEpA5kPbTseg6a0Mk3QBCMexdwH99/559fknBitHfHjiNLbEekmmrtHlfTQeeUZ+1/3NF4XavY4wH9YdeGx+/gFy/NS4OxAChslbJDXaPgpp8ftmJ9Y1nklLOJGRBzLXc8o/JETkGRn7x2ZFCmFouyjlVet2o+5EFXfZC6IaiSQSV8ePJRCRlHGs9o4YUdOxn8/ttHfpuaWrvnXSqvNO7H/glqTLsTCW0ecyfZRO1QUkyHZTpPoYy2kZqalU90XFWMCOhUydL0oJgqxkKGz/xddXX3hq761XvYPeGGQtefzgQ/jRwfjuffj0LegobMrKP3A2FhG+F21ZN2ZULkPl158rvbAUbJm3zFfa+PuyyOSysxdok0GukpRCaG2OpaysrIkMrGpSGQw1iFuZA9981w5WvF5+8QkdFJ3miYNF6XSxHwwOfV0cMOQ1UCEjyl1EBE5PJ2ra4xyuTChNEkSTJBgdIpZw0kl2ZeGpe/OsR6SQpwb64txIczhkvBQsfzXsbs/NWThMIu/snIXZOQurPnQnTWs+4UutF/930rs4GVUnYHz7k7WF7pmiMNXxOGmWk85SqDhOaEweq+O7qvJUrbhVSkkqYQZIUyKk28lsQyKVAOqje8FKqf5e551Uocjvsp83ffbqJ++1h8p26qYmMIdIEJ7RZEhPDB0Nrum+nUgJVwNQwQihk7FggCwXhAo5/rswOxkDveZWXRooPb807FgFs7uwyW23qbjtBPz4IRxyDb61Lxa/O/u1738bWwjfi9ZexNzUCyhY+caaS78I5tq9PxK0ryo//4jFpJFVPCs+fX/H/10AIeo/dLy7+dZh+6q+v1+ni2nIgcXugZVFWZlPnOoJIPK14z51QfGFx/vvvn7AfkN3J5/3O1HbkL4sP/9AMMuGFqdlktWzjdCCqEDPJ8sMQcQJOLAnhVzRmKTINJZYV2Dt+26/pv+uGyafd/Vgnq21WX6Hvfi4Uum5pcWn77MNElL1drb96CxWYfPxZ+cXbOjplxW8JcHxmzfukMUCEipoZ6JzUoYlP0sQ9OY2A6Mk6EGoeSMfbxdvAajUBeaxxFwByY/vslh7yyVT1U4BVqbI0LnlFxyUnbVLZsaw87VGa07zxHGnnV966fH+e25OszVE7awiJiCAo4lhjNMUAfYurmKESPmQYm655K6YEgLxLI1Umbqv/0nh8XvcSVvULjmyZtf9N37/h2EZia/sgQ9thS/8HXe9gfP3QY23/rvGbEQ2thC+Fy1QFaqeBngAVrkd98Lj/yoD5iWoS/09f/utzNeWl78OgEA1ixbLxvEA+v/xBxQHPdf+vZsXqACr8itPcWGAw7KobVRdbbJlkupsrVl0aM2u+/X/43qAwMwgDNLvJunU7L7Y/m4V56s4TQhg8642RSziQ8BYDilaKlICSah8j1usffoaIf23Xi4++S/ZNEH1dtbte+S6djuFqFl4sOpcXXwaIAmEHJT77rweQkCh9NLjqq+bywV3s61z8/YYxsgMVUO+DgCkhFaxFoRZ4YzH7boVv4ItOYwAtCmyq2LEXpN++Ud0MJWeZeLksor1Ne3VBGsfr5GIRz9+moiZFuwwgQBkZszJ77zv6BwyHAtWLSssvTO/837uZlup/h4TpiNZCeNvUBUTI3KR3QpmQzWQ8OZw5Zexiv9F3a9ohp1pgqAM34Iys7T84mO6v5tLxbCzDQBJp27fI985bwzHdpqEvx2H8/+Fw67Dzw/FFoMSCMZsQ2xsIXwvWkainIounAmbTfrKLzn03albFR76O6J9nnD5a33LX40vY610cUA2jgezyThIBRNmp66a+rL45L3FJ+8FYF8XUkDpcM2K2r2OSF6yYcB+CfnatbXWJnRwJb6bk91ISyWapK0nRfEeXbq10QZgCgYe3cVBwOVi17U/DFYts21WYcMRp67TnUYy0D4qbFserH4rt+Ne3rRte/58BR77BwAIMeXCG0V2NG+Xlv84x3/zJdkyWfWskbWNhcfu7r39mminzm6NMkAJn0Bq17SCdrWCpqBily8uTZGRIqFLRfyQNGlqaiySIhu2mj1zkK06PTFYA7Dz5x2z7ht+Wn792fIrTzWf/LWua35Q2ccU1Wr1xKjmEwDindEU/2oVCwGnnJYwCSRFERdBcm/hiXvwxD2AXThVefCXynfB8i6+dwD+/DJOuAlfXOAcM/fdbtD7yMaSZd6L1pJHe+WLyJm4ueU62WJbEMm6JgCUyQIQmRy5HjmubGixIGIiWd8EAqQLg5MTEgQDxzZwdQvrFoKkACxSm6QHIOxY3fv3ay1SGyRyNTboWYt5W84CIGubQBQBwMnmJrgeAHYcEOA4EAQhIKWFiiPKo3FcIiKSJBwiQgwzB8h1iQhCkhAEErm8yNd702YCEHWNEMLdfJv1+tPbfGsQyfpGAKK+GUSZbXbwtpoHIW0fs/mOK75VWHrXSEYJ/rIX23/5ja4//Lz3zuvCtrcyM+Y6EzbzttgOljQgxnd7ZJI7TGaHHDwWLhAVxWPhZKwTiEgKCElE9rEGzihdmGBdCBCR48SAeguul1GRSY2xEP4oI8bA8IUDittp7nKIyGnY+BA23d/d8Ztvd91wKbQStfUA2C92X3+pAUXAkDAknABuMkujiUFDTgySZPkKYGaOuRfCgRAQAtIFQaQR99Kx4pdOkj6GqPsmu4pM0pDjARi9FPA7YEdsi+uPwmVPON++V6gRcEuM2bpsLCJ8L9r0Rjy1loP52j0Oy++8r8jW9LWt6rnoPwHkdj2g8SOnGpCZzbVjVl1rDKQaSIKGCKjug6NE/yoMe+gDqJL908V+1de1DkXcxqM/U3/oySJbU3rj2fZLv2wfiAAxYCMMwEAYJctUNSaqF1C2MEw+tJnubP/kuTig+rqajvt8w0dOFdka7ZeGE8bld9k/O2eh8HK6NCByteZn4Yl7oO1jdaG//MqTqmNVzawRKD313/un0ouP2T3PMMxuNx9A2NVqlA5TXUhDv60IRwSNL1eMhUo8g1iPMOo9I4LemyLze0zPFob2gaZeTmIm+4thPDAjEsPwbYqN4T0I4saYLcGNa8VnHiw+fT+Amt0ONkKAQdsKv3V5hKdhS8IQRPqXsWeGMTEsXUMibwlw1EdoRLwQpqcpGH6YqtE4LTSxsuUFNHwOw5fz3CS2dTNuWFI++x/ZU/+Cny4eAxpuBBtbCN+LNm8irnxqraUiVwtA1DbkF3zIf+2Z/E77kJetuILIGT8lbFsB4bAOLXBYazguwrKFckuXdUggEFhrMsKBXpbLJbguh6ERTBcN47wp09ebRi/ydZ1XXVR+5UnhZbUKABBJ6JAcTwc+eR7KARwJrdlSQLNwHB36wsuyX4LjsNLmXIu1EtLlMICXQbkM1+UghBAEZmbyMm0/PtNpnhR2rK5ffFLtnsOlOzFKdSa0JTez5tIvhWtWmFCMVShyNZTNxaeew7T8zvv6y16QTRPCztX5hTbpxmmeZAMOFcLNsF8WVrzegVJsICJakeNxWBZelv0ypGuVBQmsFLkeh2V4GSqX4XisfUAYemhyXAQ+3CyCIqQHFRBJJibNVonQzeiwRG6GA6PPwCAWBt3vZHRQFl7GahlyyADI6Ca6HJbJzSAoy5ZJJJ3s7BFLP67XMtvu6E6ZLuua3IlbOI3jfXpZeBku+3Cl2dg0E4Mch0NfuFkOypAuqzBiY9fRxMiiXILjWQ0KkxUsHVIBuRkd2O6TEGzUTUhCheS6OvDJyyAoQzqsjf6lYB0K19O+T16Gy2VyHYTKxO6sQjMWI+Jw2DRW6/GvD9Pf/Jc87g+4cgmasuu/ZczWYWML4XvRZo9H2wBW92PSWg/mAKDxmDPFkPRgzGH7KtYqCRdMrOFrGKy9ZmiDR47uMP8sl8DaoLYNK1vjR07LzVu0/hZrVXjyX2nyKrasZnEUwhYwEFWqfYO4L0EbgfikMVqXAaBcThqjooiwVGDAL/RD6+IT9+TmLZL1zQD0QC85LmXWL1jFKvTfern82jMVzS/0TTnn/0Sutq9vBOze2TkLJw3CVISdqzkiN7AkAwZxb8nSomYYOHy5xGzHIuFRi6gGmLXhE4gB9ewrAGRQ83YEjdZjdLQWlMBsadOj0TeYAcO0oO298cmruUuBof0yWHubb9N8kqXQU71dIlejB3pkfcu6ieiGY07L5Ilf/gUA1dMRdq0Ba+2XGExBxcRgP6JiYB15xlo0MUqIPROfFOqQQRyzEHBaIdKEfRrMhlUA2k/XqA2tgWGiCHyAoSpoH0x8zH6Z/eLwM5bfaXMEvncALn4Ax9yIa49Ey1j6zAbY2Bnhe9Ek4cAZ+Nsro72fqPGoT2dnLyTXs3hkSpDI5rDE8DtDCMOzFcHbIxA3IbP1vJpFh2a323VYNQppFiQyTM3RuZStKwVVJnPilRySVYK4ScTHh/an9EAG+CxAhBQq3F/x2qpzTygsvbP86tMrzzlu1bdP0YV1CQ4YW/PTr6z5ydnk2BrN6amoaRDDWESHY7Jpgj17ixyOxOGCiCy+23TcjY6szBkhCYDs/nbaCSIiRDUPdOPjVYKwd6XZEuwxm5SWAdyAzeNTScBSeBOZItNCYRi96+x5WPHJe1ede/yqbx6/6rwT26/41kZxDoCBB25Zde4JqvVt0ySCwb8njUmPPqTDZCI3WT0xKkgDKE0XYM8LhUNmUqUeWzUVzcQzHbeMEFLamUbJLBV1jeyXV1946spzjis9V81B8e7alxfh0G1w3B/RVXq3m/LvbGML4brsgQceOProoxcvXnz55ZcPeUFbW9unP/3pgw466Oyzz+7p6dmIVR+9Ha57DqM+C89uNz+3/UIOA6v7w4mIkj13USGYobWBJHNKvoeVAiM7c+emj3+uWuN7baaV1bVXytRogclWZT6AyetjMDMrDY5g0WFcrynT0TlN3JgAbHL5NJjto8yBULkI5mD1W2H7SmilB3qKT/4rWP1m8ZkHdWmgqnml5x/xVy0rPvNguGqZbaeB9msFBpcGuDJiG7Xpvm6wTiPlWcUO18ycRtnbjmjTfQ3WAKfv4th1OiEoMK4j4zRt77JQ8dQQs1LmmZzGoavoZNEMkwkNrW57iIhwAEDQthzM5p9h65sbxTnlV58pvfYsAFUuAHb0mRWQNCZxFwAVEgOmiCuKItkvDWZwhdMQhGATIzKYK9SywmSGM7OZeDo1FVlHE8NMxUABUH09xafuVT3tYA5al28UV1R75rVnghWvje7esxbigOk45U8oBBu3UR8gG9saXau9+eabixcvvuSSS2bMmHH66ac7jnPKKadUXbNkyZJZs2add955P/rRj04++eSbb755Y9W+22ZwBP7xBvafPprb2378edW9Jrf9IlHbMPDgrQkey+ro6gRJZoHtglmxIGhkZszNzl4w/OM3ABBy3OnfLj33cN89N9lXtnmsAXsZWBsq13UhoBRbndgKjJ3BOEZ6vwSdQtWTAGsSkrU2bSbHyc8/kEuF8mvPdl3/EyMTkZ2zcNxp58dV9d55fe8tV5J0WIU2UTDB2Nn2D8ZKjs5MKq+BpUMIKG3UjBNwpMURwl4GHYEOozJJUCnYH+sUS4Fg6MFUA0Ak6msH1ziwYoiNSDIbCL9pXjIqAlBOy5Tc/P1rdjvEPLBunyUkpWxoCTtac3M2wpFh8dmHOn59XoRxFMzKgCkrKQFMYzRbPoE0/p0BmUhA24lRQThgJgZkrGac6r6p18JSK4rMh1bouJqLAGDonvbO338/N3u+t/UOtXsevuGuqLLSC0vbLzsHQkz62uXO+KmjeMKX98CX7sBZt+OXHzZsdGM2MhtbCNdql19++aGHHnr66acDuOCCCy6++OKqhfCRRx55/vnn//nPf3qeN2fOnEmTJr3xxhvTp49q4RrKzlyAHzyEfbcc1cwmAuBM3Dy77Y4DD96agI4BSKOlLpLzFcC8F4xSuTN+at0BHxtphZmt58nmif333Dw4ijV8H9Wf2zc7p6DPsKQy6fc7UqtH5c1mLfFXLuu/98/QKgmeAC6XARQe+4fq6QAJ/62XANgXHBMGV0AbcWvEjFYaGljZA07BxlP8JgDMSzh6E1syAnsZIXnjR6to2iUWLZduQozKBzGYDDQvOvxKPYrNuglisC49/4gu9EE4JAW0Fvm6+l0P2HCnFB69u/zqk8m/Y+R7qluREwgc97HCM/bnUBPCrouc6ltyRbzMJpVzheviGxLKn+Sx0VGjqG2o2//oEfccAFB45A5dKtTuedjg71uFx/9ZfuUp24DhEf4NNgK+uz+OvwmXPoIzq4+tx2z9NrYQrtUef/zxxYttGuGiRYueeeaZIAhc101fsOuuu3qeB6CxsXHWrFlPPPHERlwID94alz+B65/DsSNHzk4460fBitczM3ci6Uw484cDD9428MjfwdRyyjecSVuqjlWyeaLu6yI3M7D0roH7/8qMlpO+6k7dKmxfmdl2p9E1mMvFWGzdvE04DeWuYr4yRVwpXo8ENl5xQeXL0r7SlWag9MwDlojcWIRbCFrf6rz6exXtq0CUc+p54KCcyh/ZIONyIWmvhYNz9JPj1zNp5qT7lY3RiesGAcCrQPHpis1jLeQ+eVxyFwMguxVe5U8NIGxf1Xvr1dWrhBBTLrherJ1OYTimWt/q/d3F6XaaeWJGcMiJUU3CYNNadHwBV2LtkXKaeWzqe0P1dKqmfeDECcy6ojEqaa0OR7nzGCx/tfOaH8Bkelfy9YStb3dedRGAugOPye+8rzNuyuiqAOBK/PxQfPgaLNwMu40mqvxA29hCuFZbvXp1U5NNHGhubtZat7W1TZ2aTLHW1tb4AnPN6tXVHNbGtNYDAwM777wzACnlBRdcsMcewyL0+vpCceptuQUTChPy1QFVoVBQSg2dNQpAZjBtu7BYAoDx03jaLCy9gxqaeh+83dt5f3f2ghBAbQsAbLEdHvibqGvsfeROd17Jm7dnWPZRHvGBWfmhW8OXnoTj2mM/IcAKwoX2IR2EvhAOlGYBApktTQ4CEi6rMqQLHdrQRTMcB2EQkZa5rAISggFos78XQjrQCo4TqRgyMVhIqJAchwNfFfs7/3gZHBcqsHkorEg6HAYkHdY+pIRSIIAIWiOba/vtd7wd9ylvsT2N9lu5scDJEQkWBKXgSATK1iikWYQslZfjIPBNHw2hj6W6ZA3pQvkkJCsDbAghTPCnSTochpAudBnSsfAJaDBISlYhOy6CMoQDDiAktAbbsTCegXSgfZKOhbIwMaxn2HhVSCgFQQBBK8rWDAQh9a8/C2ltprUuCY/ydSgVmRULQVpBugh901ohHGjFRBQheTj0kcmiNADHQxjY7rOGdOLRN20GCbuYGW8YXITrwBaBwHZi2FFwwb71DKJNeMexepmBT0KSZrsyaw3HQeiTl+VSAeM26x+VH7TMUq4WQbn3odsH3ngh96FPxJEfk0M1DSj1F996xS8WcgefOMzs3EKhEASBlBXxZQ44fw/5hdsyNx9VzDsjTjDIZDLpL/ofKBtbCNdqdXV1xaKlVioUCuaT9AW1tbWlUpKqVSgUqi6ITQiRy+XijJvZs2fncsPKUdylFp/cAefeX3PlkuoNUiLK5XJrXQirbM9DG3bYvfPKi8ovPsodq5oWpOiDFxzQMHuXzmt+WHr+Eb16WfOiQ4b1wCrTqvuW/xus/W2h3zbvw4gGRBuEQZIMYjM4os3LdO5GesMzupIQJ5Jw9E0fUQ5FEABQrW+r1reipkSqDmGSaGNzMTiKCYoDwQuPctvymrMura3doOinv9TLrC0UwoC+I+S77bhKPENhyIjlKex/VkcwndkUhYw2TSYMOHJazPQdJYNEDuc0tEDFnonyaCKJCXtvqp12mKIaC301ksQG+ERrLaXMn3vVwEO3dd90GaW6j9CPBy4O0wxeXtY0NJ9xYduPzkw3piIVyLIQpCdGVBQkRVx5F5Rf4RnjvSA9MRSnY1TTmHzD+K9dbmmbRmG1tXXnXd1//y09f748fPmJxt0PcadMj4tqz71y4JE7um/8Wfjy4w3zDzA8Tes1IUQmk6laCAEs3g53vI1fP1vz9T1H2dgPpo0thGu1adOmvf665Vh5/fXXGxsb6+vr13aB1nrZsmVbbLHF2p4mhNhll11G0Yz/no8T/oifPIKzNmDrv/z6s12//4GoaxC1jfld9qtuW21jfse9/Ldezo/6NEhIp2WS6mg1IQ4zSBoUc0b75RjFbBDlRMQGxB0EwsuwX7ZxJBl0P5uYQGSyulyCEa8XhhCaIRyoAF6Wy5FGuZDMTIiCRTfDUY0sHJtVKARpTY6ngzJlDJ+AA5PFI4iVFtk8hBzsmVFYdusdnHFTyHF0oU82jg8725zmCaprDftFDgImC+ImJ2NE4REYQL0CgWFCNyNDn6GY94AEmBkR74Hpo+tyEJIUDCZtjn4DC+F3PR36JE3cQywEqZBcT/u+RfdLh1kBREKwCoXj6cAXmSz7JZYumRjU8B7UNq6bYG+YRpmcO3m6JZPTyTCRX4bjINQsIISkXI2sbw672/Pz93enbClrG1SxjyBBQtTUitpG1dNBjqN6Osn1DNaeGGBN0uGo++R6HJpdBE0MMzFSU9FnGxHGE6MCaw+tGNEsdV32A9kyftSrYOfvv++/9gzlanSpQNKB43b8+lzZOCHsbJVN43VPJ+VqdLEf0iHpdF753cw285qOP7v7pstKzzzQeNQZ2Tm7jbTGr++Jg36HE+dh89Eob35AbWwhXKsde+yxn/3sZ7/61a82NDT86le/OvbYY83n11xzzdy5c+fNm7d48eLTTjvt3nvv3Wuvvf70pz95njfMDc8RmSPw00NxxHXYthmHrp9Wc2jaiSi0AAAgAElEQVQrPf1A2LEKHaumfu+mIVHn+QUHbYggke7tDDtWQ+sEwm+ikHIRiGTTK1HMhutL+2XoCDUfmT2S8VO46Vh2R4UAoVxEpN4eHUBGX/ONDnu5BCQ1mmjMIqbLFY0xoZsu9E357o0jBdQPNg582ThuwhcvJcejSMoHWpeXPb/mJ1+s7L7B2qcB9dFDfNORMmsdoebjsM9woZXB2kq0h1Euh9ERNDLrBq2fhNFgGJ8YoDrbgCyKiLRfAqANUF2XOXILAN3boQt9VSJco7OwYxXHx2xmmPwSM5MBrihoFY7/1AVGXxqA6mxT/T2AJQ1o/OgXs9vvTtJZdd4nwNrSDsT+1BGNXDIxIs/EfAIJoD6JlTlyeGqWmrQcADbrSnW26YHeEUs6M6vujsKjd1WcuaowLBfDzjUAq+72+BwXAKsw9Evh0jvrF5808NBtXC4WHr9nFAvhuDxOnIefLsX3NkKS0wfFxhbCtdrixYv33XffmTNnjhs3Tghx++23m88vueSS0047bd68ebW1tT//+c+XLFkyY8aMN99888orrxy8U7FRbHweVxyOT9yMljwWjuoYvGb3xcGalZnp2w2He2Wk1nX9TwYeuMXbai65XvDas6xCMGC/UGc4KMP14Jcp5rUSglVIjsehT67L5TI5HtvDPEAzHBehT9JjXSLX4yAgQeaMkByXbUhkiyCEWSdJSFYhOVkOSsLwaUmHtSICSLIKyXU58O29jmv1b4XMbDXX22p7Q1y3Iab7u1df9CkuF8AsauonfuUyk2PSdukX/WUvmBoJzAZT4XoclG1s5zhaBUSCQMzanJ7C8eCXrJeEYCZAkeEYczz4Jlb2QdIA6czBKjkeB2WSGQ7LJCVYszkiVaHwPO370QUOK0VEbBzuugh8cl0baIYxqxmLmnrK1WzoFAEAyOaJJASTgBn9wCfXg1/2tpgpGpoJQtQ2eFtul1zfNL7ugI+HrW9BOlwa6LjqImfc5Ilf+aWsa1Hd7eTEYR9DMzmSw1C4Ge2XyMuw70MIaIA0CRMsevAjh1dPDC+ZGNKxfG/CBO4eB74qDqz8xscbjjh1RFmjXdf+cOCROyiT43IJUpj0H5KSw5A8z0auZixYE5hJQoXCy6w6/8TMlrMpV1O7z0dH5+pTdsQ+v8WXF6Fl4/+5vz9tbCFcqwkhfvOb36xcubK3t3fmzJlxDsXDDz8cL3jHH3/84Ycf/uabb86YMSOffwc5jmaPx08PwRm34IrDsdNa6a/Xas7Ezceddt7GbxYAIFj+KgBiNB5xWuvFZ9hPTTqeOQkLAo7PpcBWgtwEB/ak0LcnZKkzQnvqYwiRKw/JIlrqAEjYwiK6AB9Rgp/9hGFJtmyNfvI7wErXHfKJjaJAG3at0f3d5nfV06F6O0W+FszB8leZ2R58IgpQDJtz6APMFjYe8ailzsAswXQsQ6+SD+1xV6wGHAZVF0Sk2xyRWVedEdodZURHlUm98dEpoAd6uVykjbE7qns62BAjxP4PAwDulBlNx5w5xA1EDYf/h/m1945rSy89Ea5ZwaWCLvSmPDPE6MPQpNmE2xhln5pO65gYMR+3ShjAUSoACN5+eZg9ZRX6rz1bfvNFwHCdc8IRmJrA0TCFsH8uISKeel3qazz0JG+zrYZZY5U1ZXHQDPzpJfzHjqN7wAfOxhbC9diUKVOmTKnIaTZ4idjq6urmzt0UymCLNscPD8J//gWXH4ZdJm+CCodrTcecVXj8n/n5B4hMDkLaF5BFgkuwwSymIfwAWzijPa1JcNMAUgBwrUhI+7Izdxm4mMGGGyhkdK8RxSUhWGkTHcY1Gvg8S0GhghQIbY25nfbJbL19ZvrsjeIHb/Ntmo45U/V1A5CN49xJ02xvMjkK/BRpgOEEEGx7N5jcQDJbhXrb/QTSIIH4LsGsKUbLCQEdUQ1IySq0EPvEnwJKGf+kMIgGYSrA2iag2oGzWrjkZiwr2wYbmZjbYtglq9CdOC0zd7fhQNRr9zoCSrmTtxQ19c0nfqX41H399/3FaE1EZmD4EnrQxCBiy+0w9MSonKXxMEWMENo8VpE7XGbr3r/9tu/uG8nNAAlI04yToUQwNVY1Js1BEXa0rvn5V+v2P3q9Wptrs8Nn4mdLxxbC4drYQvjvZPtuiR8fjNP+ih8ehPnrEYTYdOZOndEwdQaAsH1Vsp6lkHRcCZo3RlwJ9koXATHWjdPcKIjB5vZ3DRDHGrOp4xaOr0r+KTgJdczV2Vk753fcu//eP7uTt8xss8OGu6JKvyJsX1V86r44KzJuXfKzCgxnC5KeMiovoFQfuBKNH52VIXFdRYUVzq/8Jw/ZpBhCEI1p6aXHw9a3ycuRoPz8A0eE/i4+fX/pxcfiWmwfaxsbPvzJ4dwusjX1h3zC/O5tOcudvEX//X8FUhMDSZ9TE6O6j0NOjPQsrXRM/C8GIqLXdRqHwcBDtwcrlwH2JJJQUSUbzgRCMkLV84IBi5iM6e7SFqx4rfTSEzRnETLr0sTYfTN8+m8YCMZEmoZlYwvhv5ntPQ1XHI7T/oLP7OycNErg+ztlhto0/hdg3suMId/L9jVVhZc35eZdkOLCqpIUhwY4leROcRGnaqxiy4JFb6cg1UHQ988/9t56NUlnyoU3bPQD1K5rflB+/VkytDVU8aazy1xahz3+Jf1+1BWeSWvZMzRV3Bv3iyuWNER+SHc/9cTo3sGNMSWatSJAF/raLzsn3ogW9c3ZWcPNglZtb3f95tvpx5J0mo4/OztreJTug4wyuQlf+N9wzUqRqyk+dV//vX/mVEeqEPop6D3HY2C/PEVXJHMmmaXJgu00jGs47JTsMHjmBh66rfvGn6XqHfRFj1MOr56lyQS2ba7gfrLWccW3ws5W782Xcid9dR0tyUjMHIfn2rBgDFw/DBtbCP/9bKdJuPFjOPlmd1kf/c/ecN4zxOkiX2vTXhiG7zHBsIcmeUEREYPAmhzJoTaA+mT/E4bxK8pt8cssJUw2OzOzzYkg4bLSJAxEWhCDoS0CXTp2bzC0+4TgCMMuJUIt3KwuFww0W9TUm8VPNo6D8w58c/aMyryDwE/oPY0fhGTNBnEP4UCHRGT4vSJ4u4AGycgzBv1uNtOkg1i1kYxUobYPMbkeQkbbpIY0QEZ8AtoA6u0+KsBE0NrW6DgW/m/264jALLI5s8VHbkbWN6meDhISRLJx3PDdQLk6ka3RfhGaTfdFrja/836FR+8uvfioyNdzUAKRqGloOPTk9SLKi888UHzyXlnfpAv99YeenNlyZv+9MGlEdvTNuEcTA8KJAPXawOpJVkwMOA4CHREOCKhkllqVR0HFZx8sL3uRywP1h35yHYL1Ml8LwLLauh6XFUmXdZmEgGa2I6hYOhatH/ipWUqsNUmPQ9NCFacpqe41vbdcJWrqVU+HjRg7V3df92PhuuRlGw47hYaavVs3443usYVwWDa2EP5b2paN+H8fKX35ntwJN+FnizHuvSFFpns7I635KCWkAhWu4rAt/rAC342oKAWNR6Tebr/Jp1H2BniuoxwTlcDGExkNU5TSWJAN41qOPmPNz78GQPW01+57pDdjjqxrtOJHG9V4oC9uEqdS9pMuGxYeI1XBUegcpruQ8kysy1GJKLfhhE5pMoSpGhkVfALWPxG0wNSYFgmJN3KZAehCH5cKVNtArjfpa5frgT7yMgCPSJZP1DVO+uaVAw/f1vOnX5vuq74uVmHX9f9bJfqRnT0/M2M9J+7df/iF6l5jfpcNLZTJAybxhNLTI54YFTD8INLlMD7VKUB92jMcxY5hACBoXx2sWWlrbJlUf9Bxa2tb2N2ByIdENOHLv2i95NNAlO7EtmpLiRBWNSY1+kYJpN8K2vTf99eBR+4wv5MQAMK3Xwnftjpt2W12yA7SxQQwsQZtQ+ytjtkQ9p6JJsZshFbn8W8O592m4sPX4v633+3WAABk43jK5iGlqKl3WiaJbF7Wt4CIMhkQkeOBHEhHuA5IkJcFEXlZkCA3AyFIOpAuSMDNJnd5GQgB6UA6EIK8DEgINwMicrNEghzXMERb8cVMFkTwMkQCrktSQki4LpEQ+TryMrmd9vSmz/G2mCVqGzNbzwPgtEwi7x1R+BaNtvtEAo5LQkJKki6REG7cfSLXg5CQ0vYxkwWR8DLWM5AkHXIcCEFuBiTgme5nIAQcF44DIWG672VAJDJZGM9ISULC8SjyjMgYp3kkJaQkxyUS5GZBJNwsSMDNQEqSDkkXQoh8bdulX2z/5TdWX3h6++Xntl9xvurpGIU4rcjXZmcvkA0tZmK4U7dqveTT7uTplMlSJmuGSWSyTtP6teBzO+xBXtaZuLnI12W23Vk2T4AwXRAiUzUxJAkpHC9xtZclpCeGR2QdTtksQOR6IAnpkOMhLorHQoh1q9XLlgmQklwPJJyWSe6U6dnZC0Q27zRPFPVNsrbeGTdFZPOivjmZpY5LwoGIxsLLxOMom2wigNM8HkJQvpa8rDtpS8rkKJuDkCQdcj3ZMqn4zIOrv3t67+3XpBuTkShvHALd97+NRYT/xiYIn98NC6fi83/Hkpn44u5w3xEc43AtWLOCSwUADR/+ZM2iQ2HUoHrarW54GOOmAcTi9SWwNul/jCi7IYh07ZnZYu0j/IBfAkincNMIY0C9D4AjpDYYCOJoSTHAxf4p37nBYPsmfP7H77Q3OPB1dzuYuVwGGGEUuSLWi4f2i2CuiooM8p39cuKZmBFMx4B6tjmTMWpeJ6hwbSTaY88YdrdyEYAuFwEkgHpEOPRoLGDHInpqoV8X+lXbCmYdtr0FoPj0/e7UGaNwiDtx2uTzf29+b/vxWUHr2+6U6RO+8JPW755u6yqroHV5/PZfmzV+9FONH/1U/M++u66H1sYzujzExIi4HYwAfRGonhjGM9EFVqHeDlY59ox1eNjRCoADnxx3cLqQ6miDUibIC9pXceCn5cBia/3+Z1RPR/XE0MlYGN4D1dXGYQCisKMNWnOhf8qFN4h8nerpWHXuCbDTHsHqt4uP3x22vtX/r5vrDz4+rsVXcMcineHZmJ/+7W3R5rj1eLzRjcOvw/Nr3rVmrPnpl9Zc+qXMVttnZy/Izt3dfGhk6+FkADLRHpnwzgQ0gPkJ14MgCGkUw02+vpVZN8Gf+cosBFkt9QwA+91ZOiQESFiddzcLgLwsCCRdCGkDSpDwciu/fnScy/COWmHpnSu+skR1tgEgzwPBhHQgadpJXtJ9ki4IJl6MPYPYM0RGLtFEcvZDey+RdEgKCGHYyyKvZgGC44JMkQTB1uhlASLpgiSZKJyIvNRjHZeEgBAkHBCZD+FFI0Ik1xkSDdPq9v+YN31O3YHHOPUtlM2zIBKCpNtx+TltP/zckLnEa7PcjntnZ+3ibrYV4olhguNoYsDwutkuZO1YkIgnBsXTyc5SSULAkTZYj4fJcYmE0zSx9OJjK792VOvFZ6Q2ruPG7JWdtUtu3qLMjLnulOkrvnRE722/G9xm83dBXqZyYriVE4NKLyxd+bWjVn39YwMP3eZNn1N3wMcN3Z2oqad8HWD/ZLquvihY/lpm+pw4sdZYZxHNY4D64dlYRPh+sOYcfnUY/vgiPnEzjp+Lzy5AZhOHhlr5b7wArdwp0xuP+nTycV83AIRlIBKXZ0T47nL8EzYkig5LElg0OCyDwRyBjnUCc+agnBybwSKgbUDjlxMkNWyN2i8CKL36lL/sRW+LmaPWfhuOlZe9AK1Voc+2lqPTuyi8Yz8Nqa6kz057JkxQ80nUG3c/dYjIkf5U5ASOjlejVNPoLh48FunGxFQDJgo3d8UXMIKVb4RrVsT6seyXghWvy+aJqqfDm7btMP2Tm7dHbt4eAAxG3oIWoQH4y19lvzT8DF6nZdK4T32n8+qLg+WvRV3w0xPDhIbRQWA5GYu4++Yuv3KWWqeZE7vEM6pnTdjdymEQrH6Ti/1UuUvsNE8c96nvmN9bL/ovAOVXnxncZnP4V9GY5JA7HlzWhX7bzHIxP/+A/DzL4KiL/VzsByxpAANhV9v4s35kv3dG9no3Dt56mF78oNtYRPj+sSNn4bbj8WonDvk9Hly+aesWsvmTX6/d56N1Bx6T/ti+zkweSpwNKAgAORIAZOqnEUWKricpAZBwGOZzqrqehANTZO4SAoDNeTE/rdwukZQ1ux3S+JFTa/f+CIJy24/P6r3t6o3vhJSJbA4ASZG0WUSNSXWEKFUUdZ+dpHf2gqiPFolhnZDuoy0io/sqZPRJJOEbXU9CUnRB8ljHrbo3boxJzTCDZRrT/68/rb7wVEMnBKD91+e1/e8XVn/nlLYffq7/vr+M2FG52iTjkQiAyORGkcFbf+iJtXt/xBk/BQBRPDFMHYR4Osmo46aPIu00J+l+dE00gkmRqKmTuVoAws2s+2hZZHIAKDdEJlvjx/67dq8jRK4OSE0M63CJ+K8jBt6Q6L7+J6sv+i+zGMu6ptqjPmOhnEQ1Cw5sOu4LVaugYjzXhrnvGbTxe9zGIsL3lU2owS8/jDtexxfvwC6T8Y29MHHj8ESu33LbL8ptv6j6U/MOsiKrFWg5Vgb7zBxfEP1nsW5WYlZVoOUi9VTEmXhxaQqtSDY71erTstZ1+x3lTNwcwMrH7wGgIi60jWul55fqQh+0MkmGNqOzAp/HTASOBHKROCHuvtBGO9eqGafujX7RCeY6Ps5LAekqvBRfEjk5dVmMmleJ/G9EdJD6L35gqgpdKthnFwuA5f7WxZHJ9QUrXi+9sJQr0XKsQmiNYW9psAoLj97ltExpPPKM1kv+e3DHK6gG0mPB0YcWkl8pBWxuSs801rCxvvmX6r/vb7k5C8y8AlB85kH2Sxz4oq5Rda9RpQEAuq974IFb8rseYPY8jXmbb+tttk3h0buSxhjGu3jam78OxBNDA+DyALQCXADezvuJydMKS+8EkN/tkMGptk+txpS6sa3R4drYQvg+tINmYM9p+NlSHPJ7nLoTTt15k++URtZ8/NnF55d23/RLFAfil6p9L5sXETOAzKxdahZ8iDIZBnGpIOqbdGdbz62/U12tg1hQABg52eQRAOr2Ozq73a6qp122TA7bV8pxk3VHq2ho5mIBRCJfF7+tKBIx3+idDVYta7/8mwldFkCu1/jRM3pu+oUuF6sWszTBTdWJWPxiRLxGxkW2z4YDLMUyYwrjh9tPKO1rs9VpoeZVqHn7K8c/Y4sIbuK72EaZ0YLR8p/nlF5+0mmepHraczuMTARvzS++FiMEklZpPaIzwoEHb+u+8acQcvJ5v4vY0VDhGa7oJIAUZR3iT+0HlbwHkf+YYWSjufDwHbZYhT1/vnzggb9N+p/fAPDfeqnjiigvJsKDAvDffMlf9oLqXlN/6MlVLechu2moZwz9QVV55UfulrPH/dcFAIYEnPztFRw8SqbSD6KNLYTvT8s5+OLu+PhsXHgf9r8KX16EI2bGRBqbzkRtY82Cg3rvvlEVB4ziAYjJvN6NbH02qwsD3mbb5Hbau+revn/erLpaK7gxCUSSOWQjLGBQ4VKy1rl5i7yIMtQyaK8FjiYax6uBXrExMj6qn5yrMToGAIz0OWXzNbt9qO8fN+rWtyAEWINh4e2mX0JCKZKCjTweDA2pYQqVrBUbUkqKqHOMcoVwWPkgASj7WJM3oUIIB9qo26coTAVBMQmHdUAkGIqEMLBFw6UJKRFaRgIDzAcTUbpGyUqRkKyYiEDU/8AtQetbtXsdIRvH1yw4aODh2/23XvaXv0pE9YtPMjkmQ5rqbOu98zpZ36K6Ws3eZQz8NxODvCwNg8wsNgNvF7ka8qK9SpJAas6AmDVLw2Mg2NKQGgLbhFDUYtgN7wFVjIUZJhYEhYQRQghWirXquu5HsqElbFtJwnAmkK1FCCgI19V+WdQPkjMkokyOSwXTRDAbHt2I3dSB9kmKhGiCWdTUV20aZ7cbmpqnrHDTS7jp48P34gfdaOhvJWO2Ua23t3fzzTfv6elZ/6XDtoGBgWEq1D+8AhfeB834yiLsOW0jNmG41tfZ7q5+vf1X34w/YYCIxn/2B+6ULVVnqzt5y8GpK6vOO1F1rxkqIETMjMxA7aJD6w88VjZPGGZj2C+FHavdyVsO3dS+vrq60SstqN6uwsO39/ztt7aZUk695C8clEsvP9FxxbcGX5/QzYykyHwDWItnyG54DlFk/T6I0M6+ie1j11JljGBJ2+TzrpaN47lcXPHVI+PHNp/01fzO+8bXaK2LxWJNjd2j777xZ/33/SVqZ9wYG2iaiTH1oj+OiO4uXLNC5OtETf3q754Wtr6dPK6i+4bQfKg3nvVMJfN7xQVrLbLfJIZyuBlBb/rcpmM/504c9Ien9YovHc6DSdQMC/qg0W8+/uzs9rvHYmGFQmFIhXpjv3sG/1iGK9ZPZj5m1sYiwve/LZyKm4/BLa/gnH9iUi2+tDt23sTiFW4mM2OuyNVyucAgQULrUNY3Z6ZvByIxZfqQN8mm8apnjaht5FKJtSJoclzK1+neLsrX6f4ucjMIfH/ZC51Xf49ZOy2Tmo4/e70EMeRl17YKbrjJ+qbs7Pl9/7gRbpb7uzOzdoEQvXf+v/KLS8nLWrUpowLhZjgokZeBX4LjQgWAYAK0JsfjsExehsslcl1WIRGBiaFJOhwEws1ov2jZ7IQE60ihPoSXYb8k3Kz2SyRdk4lqwhrhZbRfEl5Gl8twXCvkKwQpFYsjmsaYGpkAxeS6HJTJ89gvkZPhMIAgc7pGmVzHr88XTeNVZ5vI1epiPwnJzP13XV96/pHm488eWHpn/71/lg0tYXdnIV9r01zLJQMRMd3ncpkcKwovhNAqlA3NI+U3iFNYZX1L2Pa2mRgkjM4fIIjD0NQIN4OgTNKBUkyRNKZtjBc1RttlUQ0ei4AgmAisSbocluFm4BfJybDyQZIMg6hwoALjNKd5/BCrIAAhMjN3Kb/0OKS0iaMkoEM7FnUNGOgTdU1cHICUlM1lttt1mJKZxRA/W4rLPjwiF37QbWwh/EAYAR/eBgdvhT+8gM/cim1bcNZC7DhyXcNRW9jTHmdSaCgAqqdDlwsiW2Mjg0GmutrA8Dbbpnbvj7Rf9j8MNH/iy7md9gHz6u+epvu6DNY+WPmGud5f9kLdAR9317KsbjJzp2415Ts3pCOevrtuSCTRESWeWNx0CczV6JEEPmGx9skxoE7hRsxdOgKWGJCAXwZDG0aCCD1icj10uRT/jAH1UWPK5l6OGpPUaIt8cIToiNH9pYK//FWsfC1OgzKIBX/F6/6K1+sOOKb/npuDlW8Ey1+DkdpLGQclsEUsxIANbdjXujt0uSiyo6ENVN1rosdGoBREQAjzoak3AZYk5AapxnB0lByNhV9KjUXMiBYNU+wZhFFuUYRyYaju9rW1dtzp3wqWv9r6/c/EzY/bKXJ1k86/BkQwKl0jgfr8bCnmT8G8jb/3/362MfjEB8gcgWPm4J6TceAMnHELTv4THl25iap2x0/Nzz8gs+V23vQ53pTpICEbWkQm33n1xcvPPmzgwVsH31K339HuZlvX7nlYZsac7JzdMlvM7Lz2R62XfJrDoG7fI93NtsrNWehNm5nZZofM9Dneltt50+e0/eCzHb8+bxN1aR1GlP7pNE8CETkuhICQcBwQCQP5z2QAguORMNB4J6LXsoB6y6NmmNIMxRoAN7rAwMZljLUnyyTgmsc6hk/AcoxlMiAIwzTmGJy+iBrjRYh7w/cmyJAbmCJYcgO4HiiiuyNhSd3cqEYikg5IGJ6wtu//t+rrBsGGd44lNzCELOYuYdD9hnxOSHI9d+rWtfssGd0qCEA2jbc1GoIFEhQB6kUmAzKAeooA9dKyEBhgu+m+4xI5JKQZC9iixGkkHAgHJCzW3knRPpixEESua4kRCOtmJ3cmb5nfeV9v+nbe9DnOlOnxxHCaxnMYtH7vUyu/frT/5kvD98AL7bjmWXxjr9H574NrYxHhB85ciU9sj2Nm4w8v4At/x+RafHo+9tniHa5VyOYTvmR+7fnLFf7KN1Rvpy4XSy89Bq1KLz9RpeQHoHafJbX7LDG/jzvtvL67byy/+VKw4nXV11Wz6FBD4RZb2L6q99ar/TeeK730+NpCzE1vrMJw1Zuquw2cxD0mQNGGBqzsA4zQZyCOmmwQlkLNI4EAJFEIwgo+AQv6NuRqFoxvi7QJUMo+AB2k6O6Yre6dH8Bqo1fHoNr3AegUxQHihNsgwqFzxHsQi62b8Ku/O47PEFaEp+ZDbSKtJAhTtfsdmRuG2tFQvuZg1TLV1Q6OIjwVMcyFUY0csdNFgHobEZqozveT8DTufzwWkdMMtwMQReRhivYhHgsd2HsZqqdjHa0m6TRHakrdN13Wv/INHZRMHKl6OoJVywCUlz3vbTlrOD4ohTjzNnxjz00Hmnrf2NhC+AE1V+LYuTh6Nv76Mi68D9+7H/+1Cz68zaYQdarde4kuFbxpM0U2L/J1ur9nOIcfNbsdrLranPFTB7Mel154tP1X5xistKypf4+sggC6fv/9wuP/tCxlQkJrEIMEtCbH4TCE4yIok5SsjIg5wRwEqhBSQscKTYLN4ZN0oMJIf0pCKViJegIJaEXS5dCnSKEpSigV0IqcWBIrSHJNzeab4yAM4EgEsXiTlY4l4bBVd/JJOlqFwpbYbE+rXiQcqBCCwBwXWQ0jaXTYhcniISaGhiMRhlFjpN06JtH1u4t7G8dP/uZvE2D78Kz3tqt7b7+GMlkA3ubbOOM3Kzz5L7ACm0xjxdJF6LN0YGo0RUKyVkK6OgzIkRxom/yCOCc5NRZSQilYj7MdNZve6XBohkmDrQyTqG/Kztq1Zs/DhtmFuv2O4qBs8mnz8w8S+TpyMxz6sm6tqk9V9vW7MXs8jtpuRJ4bM2BsIfyAmyOwZBY+Mgv/eAOXPYbv3Y//2AnHzUHNWrPfN4LJhpamj31WD+70gmoAACAASURBVPQOPHKHLg0gOqRZt4l8XZq8LW26txPM5vu4Dvz3TkQYdrYBVgYIiSiSRhSv2BM+e4JoAXs2TDF6PawYKYS4RcoroBqnb8/uDBlb8kCYwCd5rE4Q90CkDWtyF3UaPB6D8HTcGGhFFSUVRUmT4gakcOgw8EcmK9FuSANsY1S6Lj3Qw2FI3sgWQtXTCdggWNS31B3wscLj/7BPNRlDSnH00+JYonZqMwqqkoVAJ06zGtG60uOpPlp2tOjeWPbL22ruutUq0iYbxzV9/HNJj7rbWQVg5oi7YN32y8fwYjv+MAaZGJWNLYRjBgL2n479p+PpVlz+OH76CI7aDp/cEZvXv4OVdl3/k+JT90G6URM2wCwrmKhffGJuzsL3yCoIREfwXNUeK4gbSf7BLg5xcSrFf2gkRHX/OIomLVVMdE8FopwgEn2PGLdA1XVUAQyippHtR7otNtE/KucUGt1gFUCVYHxKGmUIB2zLksbUH3R8ds6CNAnLMK3hiFPdzbZyxk0O16zM7bCXHuhJPdYkLnHSwmoEBQ3qXNQxE/1FNASVNwmwtmNRCUox/1ClQtc1Pyhtv3vLf5470u5EzwQGT5+h7KYXceVTuOnjyI290UdlY24bs8TmTcSli7GyD1c9jSOuw/wp+OQOWLT5Rns+q7DvjutA4FLRaquahJK146+HY0ZZiRyvZvdDhr+PtAnMZlJI4jAG/5FZr5gEYDbiFFO8IhAzc8Q5yVoREXOUd8Mc5aJGoHiliYg5XpGitYcEoEHCvsXN2iYI2uDBkSxiIEBHqHkDNqdBixmTINawEP5ouSMSzIpJAMo2CWQXYINYFxTzHiQgRbt+EAA228WGCoCIhMwvONAZN2UUrhb52to9DweAWSg+eW/pxUcp/oJhvGa3pkWEtWebjam12dJkIaCVoTuIGFwZJIGQhGCNqCi1vpruRL8n3yGEAxUK19UqpOFhHgYbOS55GS4XZc16vpDe+iouvA/XHIlJo6xqzMYWwjEbZFPq8NU9cOZC/PEFnHcPGDhpHo6ctRH2S0vPPFitSmP2lMrD2vxZm2XnLJz45V+IfN17ahUEwKUiks1Du+VoAweV2sOMt9RSG5Vsd00rNiqj3UjzM0w/L71rSkZmT1c81l6vVQocEG3GmqJ0k6JKedAOYRLjpT6M9gajuM9+GAJAmOp+3FnjExUCyM/bo+6gYyElOZ7TsqGYHvbLHVd9NyJHNY0xEhNph0d7nJzsRcPq2tuO2DCsYixS98ZdsPfGuvZoXHJ6bse9Vfca2TxRdaxyp80cXUdETf2kr/9a93e7U9dFlfanl3DBvbhqCbZpXsdVY7YeG1sIx2xoyzk4YXucsD0eWo4rn8b3H8QRM3Hi9th2EFfU8E02jSfpMEBawXXZ90VNnR7o9dZChzZ8e9fhg0OaYf+yEGnpslJEBjet4GbYLwnH036JHJd1SCAmg7V3OfSF61lQvA5AghgMJiFZBeR4HBTJySDwISVYs8lqCQNyPPZL5Hrs+5DSMGgnsHEDqLePVWTQ/dFYJPeGAUgQgZWG40L55BpAvWcSbci89IWDMHVXEJCUBM3MRA6rwNRIXob9MqQDpUCAlAhDuB78MnkZ9kvBmhXdN/+KhICUXC560+c0fPiTo/Y5uZ63+bZGHIOYmU1WSwDXg18yTYLjmNxXSzXgeDook5flshkLJQzZjtZwPfbLtvvSY5sQBLAmx+XQh+vBL8LxKAwok4MQ2TkLZeM4g5qoUoQY8fxpaJEN6/p7u+op/PxR/P6jG/RXOWYYo1jbNPbuUqxtFGsdwLXP4tpnMa0BJ8zF4m1GQOQd85YVHv9n51UXpYuccZMnfuWyDdwa3Yi2gRRrVdb2g8/6b7+CIc/5jA0iPEtK4vTFkRSti2JtfTZavjdKdEWGbMzQRRiS783YlIv+OGooobHyK0+u+dlXh6hyHZ4ZxPc2VNEgS/HS1R3w8fpDT1ovt9FGsf6Bwo8fy929jK5c8s6e5X9AbCwiHLNh2cQanLUQn5mPO1/H75/Bt/6FI7fDcXOx1Ug2IzNb75CZMYe14nJR1Daq3s7a3Re/d1bBjWLBqmXtv/iaqG+Z8Lnv1yw6VP/zj07jeNW1RvWs4TBkMFFM61UWXpYNxVqoQSAizYocjwMfXhblkkVZSGGCG5PoDzcDv0yOyyogIcHMmuFICgN4WTZxT1Am6TCbbH6B0LCvlYWX0X6ZHBdhyIKIJKtAeJ72fcpkUC7B8aBDmx1j4p4gMFGdCW0hHJOJKhyHgwBejstFk+hPQiBqJ4e+bYyXYd8nKZk1wBAO2caUyMtahjmt5LipIpc3EeEGroIAvC1mZbfbVfX1gDVCP2xbHnkmi6DM0jG7xyQFQkWep/2ybYx0WYUkCCTYROeBT5mcDRaVYS0nsIL0EPqWzc51OQwGHrljYOmdUIEzfrPxn7mYRq6qOEzrK+Mzf8+UNf74cTSOjI1uzIa2sYhwU9j7ICKssrd6cN1zuOF5TG/EcXOxeGtk1/6dauOGWe+obWBTdaFv4IFbe/76GwDjTv92Zut5qnuNM35qsPrN1u99quLStXArJ+XrCPvWwY69DuboJMtzLazTo3vs6BjA0xcAABqPPKN274+s5bqRGfsl1dctsnlWoaxv7rr2RwMP3x7VtXY+8nXFr+sj3R5kk/7n/5xx7wil74vtOOMW7D4lPHcfyrjvkr7a+87GIsIxG41Na8CXF+ELu+GuN3Dtszj/HhwxE8fOwewPsCK26ulo/e5p2i+CiIRo/9U5lK/jQl9+/oHNx59df8gnguWvFp99GERgLaSjw5Clg9BPBKpIsDaHTwEcB74Px4FFagOsI3i7y7psimxqKMCGPls6HPrmCSQEa7Y67EqZMy1yXDYni1qBCYKgNUmPQx8ywoabwzxLLe1wGJLj2hBTqQhqb9H9wnG0H0H4hYwUAQW0Eq6n/bJ5OAkZLfkCrGwLHY+Dsjd9rjt5Wn7X/TfOMDC3XnxG2L4KjkvM48/8gahrBGCpBowTbGPYimG5LgKfXIf9AFJCG6oBQGs4LsKAXId93/TXnp5qJiFZh+y48MvetG3cSVuS66nO1uILj5GXEbUNG6c7lXbts7jkAZy7Dw7a3HfEiEEmY7Y2G1sIx2z05ggcvBUO3gor+3D98zj1L2jO4Zg5WDITdR+8P1I90JvotpuUwuIAANWxCkT1h3yi+OS9xWcfMmGHVkl6p82uZIvItgRg5glhJVLb8HulszGjIrJJjCa/MZ1xGoO+U4/V2tLDWD30ABHYPG6MzahMP1apdJqqSZjUYZg8vAoaHwZxUZKMilSWqQoBeFO2bPxYTDy9ocZhYFnNwoAB1bWGC32JTwwTN2tDrGNpDUwXwiT/E4iAnSrB2lu9DtacAuOb62XjhKbjzwbQf99fii88ykGZSwVs8AZv2jqL+NrdeKsHN3wMWzWhsEF51mNWbWML4ZhtBJtSh7MW4nMLcN/b+H/P4uIHcOB0HDMHCzd7F9SA3y1zp0xvOeUbaqCXGJTJq/4up3FC2Lk6N28Pc4E9NEoJU1jIICoA9alNvEE7eam7bJZKgmEXYG2hexCJSARgr7AgwKEGJG4SQMKkmiZlSfJIZV6MbbahIrMQuhhiaJZRA9qrzIsx8EQvU/+h453xU8LO1poFB43Q0+sycr1xn/pOsPw1ka9jFebm7VF+7WlbLxBJ8sbujcfC9DSFBbS5NcRgp2l8fv6BfXdcy2GY33X/zDY7crko65vDzlZn3JSwfWV+l/1M7TW7HQKQ0zxx3VzbI7U7Xsc37saSWbj0EIyQcmfMhmVjC+GYbTQThL2nYe9p6Crhphdx3j0oBPjYbCyeRv8mR4Qbarkd1kr7P/Dw3/3XnwUQMcuQXTEAjheYRDwWdo0kYQnVUtwt6XuTpdL+38DbzdITZwCkFrNqJhR7PGhXLCCB5yNGo8dEMGSXQUpCpog+pmJ9TRD5pgvQVQu6yObr9j/6HeIAymy1fWar7VN11cA2QyHxqo47H62JgqHS30cAhiAoyPqW2n2W9N19I8Iws+1O61i5yXFrh00uOhzrKOL8e/BUK352KOaPhmlgzIZlY8kym8Lef8kyw7SnWnH9c/jLy7zzZDpmDg6cjvf46f47lNcTtL7V+t3TKz8z71lZIVWYKll/0ZBpHyY+qwoxza0Jv0w1SMAuDBH3TWXOiGnnkHk06S5YFtL0ymYfOygJpemYs7JzFhqQ5aYwrcuvPd1z06/8la+bJT8//wCnZXLC7WC/fwyVuESi5T/PyWw9T2Rrws5W1d2emTFn07SagRuex/fux5GzcPbu1clo61aoH7OR2nv6NTpm/+62w0R8Z3/cdUz/ETPx26ew8De44F680vluN2uTm6xpNCJ5EALCAWAkKch1QSDHZYJVASS7g5r8JEEkiSQRkXABCNcFQNKz+HQSBILjgkCGu9U8XDoQBCEgHVD0oZMBgaQDSKuPCEA6AITrmSIiMnJ9AMFJqe4Z9T4jK2hU/SraCVMEIkgXBJh2Wp45W0ReJjd3YbD8lfbL/n97dx7YVJX2D/x77r1JmqRp6b5DS1toKSDQUpAiq6CggIILS0XBUUd9dWDUV15FHV9m9If6jjriMjogiuCwyA4KooAjCIrIXvZVlkL3Jc1y7z2/P24aSmmhYpo05Pn84SQ3JzcPmcLTe895zjO1Ztdmb3z7gmBI7yKEhAMQTCYwZkjvom/bEYKg1fxpEULSvk8dmMAknRBkhCDoYlsbO/TQriml8BivZcGCIty9EHN349M78PxNV1qSTTyCvmDS7IIkjMzAyAwcL8PCfchfgngLRmfh9nYwN1epVcuiVBS7OmxwuBoSat3sXM38nAxA7dQcdzoBd6O72jbrrhM5AVcnPFdPQW3VCVwN/7i7PZ57AYvW9gHuFu11Oue5dz2THdBaD7q7t7tvfcp1miNqH6HW+0T7xWB47SVs3Ti1Ju9KbWN3h10uu1Cxdp7j+H6lvNjYude1f62/hVJZCkCKjI/8498Ek6V66xqoqrYLuStC2Q7uijz01vvNfe/kToeWDr0ToabUhv/7AV8exlM3YnQWhMCZY/cpujXqDQF7a1RT736jwrHhOObvxZZfMTQdo7PQ5fduMOkxzXRrVLVWnZ12Pxw2DjAmQpWh1bzrgrjTpu2+plUsMFWBpOdOBzO4d/ySGRjAOFcFSVLd5e2SDrIM0dWqkAm1u5o57YJOz521TQc5uCgyxfWJgs5VUM9VGWDM1Y9Qz2VXrT1EHWQZAmO19QPc6XSV4evchRC8do8xdzB6LjsgSJyrzLUVnMxcNex6OJ0QRSgqGCBIgtEohEWr5cViqyil5Fyre/5k7NjT4995PVUbl1Su/0IMjVTKLoSNnixFJxb/6y/cYVNKL2h//NpdCHScy5IlXAgOi3zslZqd35evnC1FxirFhaF3PmLq1q/5InQqmL0T72/D8PaY3BOhV1x3TbdGPYsSoTdQImwwu1ywYuE+zN8Lo4SxHXFnhu+LLpolEaqK/cju+jt+uZakNPoX8EpbrF1hw7MrVIVftaD+qlXzjQTa6LuuuDNZwmvLzvzPKO50mHIHhY99qpGYPYdzpazo7LT7oarmXkO1zn9lX7xX9Z/ll30zrrnOiIkvVG9aZTuwXfvjGzvnRUx8oTlCUzlWHMTrm9E+Es/1btJuTZQIPYtujRKfiTLhsRw8moMfTmHeHrzxA25Jw7iOLegC0SPOvzXZcfJgUEY3Du44sJMzBlVx1bBL+toO9Spj4FqXeVdBvQ4OO9PpuFOGwAB3ebtr/2iIOigyEwTOOdwXYe5Nop1agbyr8zvU2t3CtAGixFWVgUMQuKIIkl511u6sLepUxckYYxA4V1x7vGnBSDquOGsXFqgQdFCcTKfjDjtqL0+Zyms3B5e1gnro9HA6DClZQqsoAIJOr9qqDe26MEnXauSjtoKfLP1HeeH/hdL5b1VvWcMMRm6vce9kHXzTcKW8WCk66zhzVIpJFFrFOo/s4rKDgXHGij/+q9gq0pjVw3HmmFJ6Xgxtlv4O64/j9c3Qi3hjMHomNMcnkKujREh8jAG9ktArCcVWLCzAk1/BYkB+J4xoD9N1MIPIubPwFAApKlGf0sG+/xfX3JuqFZvXmXXjrjk2Ltcp/dbmC92d313Tck5Aq/Xm7kJ11yRc/QGu19ynRd0id7imGLXKd9dLqjZhyTkuvospMtdCcs9x1v4RtHcxRebgUFzlB9r5VefFAWJknPnGWw2Xthkx3zjEfOOQa/9ufwvnuROonQ5UrZXaQSk6MWLiC9rFuqALstzxcPH0h8E5r50iVStKw6dMOffKgwCU4kL7wV8M6V08VfWx+RTe+AGVDjx9IwanBlDFbQtEt0a9gW6NNv1+o8rx/Sl8tgs/nsbITOR3QlsvNhlsjluj9sO77Uf3BOfd5jixv+jDF11HBRGqwkSJK3Kdu4tamaDIazchgyhoDYPqbgfqele9+gqBQeWXvuQuMRRcV5OKXLtP2KUd1UWBKyoTdVxx1rvV6bpDK4mQlYs92euW8Is6KE4mCKqq1nagZ9pLQnBocO9hYniM9cRB+w+roSqRD/0lKKvZpwMb5Dx3smbHd1JkvFxSGJx3m1Cn26184bT15/XGLjfx8Djbzu9ZZQkEkUkSr6nWJaUHZWSf++sEueis9q2GjZ5k7nnr7wxm0ym8vRUXrJjUA8PaXcuKGLo16ll0RUhaFndV/plKzN2NuxchKwoTuqBvG39dQWdI62RIu1jffXEraqC2Obt7YSgHoFW01zaPrd0ARav85sxdAH4ZBndyq9dESLvarF8rXueRqw0tr/PfS3EBcDevv1iGzt3jmWtLm0v+iHpDyK35qqoqcan2H1YDjU9fNj9dbGvdrfkNviRFJYTcmg/A4XAYOucZDBdnquWSwoo1c13X5eAA7Ad3ADD3uOXargs3HMc7P6G0Bk/kYnh7iP75I339oURIWqh4C57phT/1wIqD+L8f8L/fYcINuKuDH98vVe01ANw7jYVPmKqLSXKe2F/87zcv+ffQ1V1d2yn00g712k1OVUuKyiVpxXVQ5UCdknntXdx9Km3AxftA2it1P+XSXOX6LNeepPWC0U7IOaBPzrDcfK9oDuWygysyM4eopRd0iWnaSDE8Juapd9Sa6kt+IfAHZV+8b9u7xVVtqaoArNs3WLdvkCJiDeldmn4elePLw3hvGxQVj3fHben++lvd9YoSIWnR9CJGZWJUJn46g5m/4M2tGJ2FB7ogxuzryH47KTKOiRIEkct20RRi6pwHxqSwaGn1p0pFKRMFQOCuZhROJui4YnetjmECBECpbYYgSdyhcG2xjLbdmsoFUVSV2lUt2hlc+2oyLghQFEgSnA6IOqh2CJI2ccgEgasKRB1kByQJDoWJomvekWmNKXRccUCQ4Gpt4YQgAhxcdXWc0Btgs+rbZARldr/kTxvftu4zXcIlT1s+ufhc+cpZSnkRACbpuEPRFh8xUYSoE8Oim3geu4IvCvDhzwg3YnIPDGxLc4EtEc0RegPNEXpq4u1UBWb9gsX7MbgtHslGmqfX8TV360TVWlmx+pOq71eCsYTXlmlNibnDzh02CGLF2nlVGxZrI/2lfEIwWWL++z2xVaP9t1RVrampMZv94DcXh8PBOddujZavmFn5zULXC3Xb0A8aYxl4l7bXzJWV2vDZLnyyE51j8GiOh3cKpTlCz/KDf0YJcUsKwUt98d0DaB2K0V/goRXYcc7XMf0Wgsli7JwnhoTrEtPPvfqHym8XAdDa1wmmYCk6EYLA9EEQBKYzgDGmM0AUmKRjkgRBZHoDGIPBNYAxEZIOogRRZHo9mMAMRgiCoA9igsAkPWMSEyRBHyQGtxLCo7SXwATo9BAFiBKT9EwQmM4IQRAMBtfniiJECZLO9VQQBL07GJGJEpNECCJ0BgiCFBF7hSzov4Iyc8XQCCksGoIghoQL5hBdXLLYKsrY6carZsGjpZi6Hn1n49dKfD4Ks4bTftktHV0RegNdETbHZZZNxoK9+OBntA3Dk7nI9UQNVvMU1Kuqo4bpDJCdzGAEoNqsxR+9ZD+yW4pJiv2fj9wDy1d+XLluvvb4GpvXN9IUPubpd0sX/MNx8sAVwrzSJzb+kmAKjp06WzAFQyvbUBWmD6o7wE+vCDVF7z9nO7BdioiNfWH2Vd/Oge9PYtYO7CrEuE4Y3xmRnuxIeAm6IvQsmiMk/ipIwvgbMLYTFu/HM+sQF4zJPdGj5ZUkX5jxjP3YXsEYzJ2OqMdfk0vOlcyZLhiDAUghl9zbFcMiAaZVvkOvg90OSQ9F2yzN3TDdAUkPh41Jeq44GNNm7DgXJSgykwzcadPFJgvBoY7j+7iigHNBpxdbRVkGj6n6bql87oRSUcpEiWv1Fa5aez132qFzVc1DkQHGBQZFZTqJO2tL+LWqeUEA5+CcSZJWsHjmubtCbhlrzru98LVHudMRPfktXWwb33zXnmYZeDfnqrnH4CsPszqxZD9m74TIMKELPrgNBspQfoUSIfFvkoB7OmBkBpYewDNfo3UonroRXVvO3jScO349xDlUaxUAW8GPSnkxOFdrqlC7E7SbWlEGcG2xvmvJvuIAd7dNr6151zazVhzg4PzSl2QHAMFsaTXi4cI3Hned1mGvKfjRmJljzHr19LN3wlXwzrXdai6e0Flb488BaPX0l5bwa/+9WMLvBKDarADsh3eLoZFqVTkA294tTNQpFcW62DZ1y/X8kaFd16h2Xa8w4EQ55uzCon3ITcD/9sONid6KjHgUJcIr+fnnnydNmnTkyJEePXq89957cXFx9QZMmDBh9+7d2uP27dvPnTvX6zESAJAE3JWJO9pj0T48thqdovFML6Q3y5ZYvxkzGJnDoS24qFgzD0wAXBWE2p1St+C+d0BVbYd2OI4XQBChqnVq2N19ARUmilxWwSRw+eKbBQGqKgSHmHMGmnoM1sW2Cbv7CbmyFJw7zxwrnftGRauouJc+jZj4Qs3erdWbV0FRTN36qQ6bbc8WiAIUhYkCl1UwEdxdMqhtlqa4PlcQ+SUtEkVA0e7TOo4X2I/sNt7Qm0m68hUfV6yaw1VZioyPnTrLG1+x16kcG0/gk53YVYh7srBqLBICo/X09YoSYaMcDsfw4cOfe+65MWPGPP/88xMnTvzyyy/rjdm/f//48ePz8vIAmEzNNiFAmkYSMLoj7szEpzsx+gsMTMFTN/q+0IJpS9JUd+nexYI/rR+em2CyhNx2v3PWKbhn7y/W9tUpDXQ91HacqV0FWttxPnTEQ45j+6q+W2bKHSQEmQCUr5pt271Zu1gMysjWxSRVf78SgCEzRym7YNuzpbaNr9aGvs7n1lYcakUa9Zv9am/jzD1Mn5QuhIRbf16v1WaotmpfltA3j1IbFuzF3N0IDcL4zvjn7XQX9HpAibBRK1euDA4OfvzxxwG88sorsbGxJ06caNOm/uRHWlpadna2LwIkDTOIeKgbRmfhvW24dS7Gd8Yj2b4rw2cs6k//Z9v7Y9nSf9bdPgZMDBv756DMBn5yXFddXEs9l1aduQ6qF89zMdNwAFyRuSJfeP9/uMOulBeHDpsIIOSWcfr4trrEVG0zFK4orv1CFdky4G5ddGLlhiWOY/uE8JjQIfdJYdG2gm0Va9z3NljY6Em6hFT5wmkpIs52YHvF6k9cr6gqwJnJHHbnH8XIOLX0QlDHntata1GbMi+9fPR728/is91YdxSDU/HOENwQ4+uAiOf4wZpDX9m3b1/Xrq7pgbCwsKSkpIKCgsuHTZkyJScn5/777z98+LB3AyRXYjHg2TysGoNjZRg4B8sONLh1WPOyH95VMuc1pazIlDNAMJrBBK37OQAxPNrcfaBoaWAfVV1UPADoDABjogjGIAgQGBhjWtd4ra+6tt2JIDDtSk6QAOgi45ggiqGRAKRw1z/VTNIZu/aRolzriASjWTBawJgUHsNEyXjDTfqEVABikNm2dysLMhlv6M1EydW9Xae3H9yhlBebuvXTt2lv6tqH6fQQRTDGDEEA00Ulmrr1M7Rub+zUq+LLOTV7NgOAIAEQjcGe2p/ah6od+Gw3bp2Lp75GZiS+ewBvDKIseL0J6PIJRVG++OKLy4/n5uYmJydPnjy5qqrqo49cq9tzcnImTZqUn3/JdoXz589PSUmRJOmjjz5atmzZnj17wsMbmJgqKyuLiIgICXEtHJg1a9agQYN+Z/BWqzUoKMgvyieqqqqCg4N9GMCO8+KrWwx6gT9/oz0jopHCAwCeDrXqgynyr4elhNTgR6fzmmruqNESIbdVs+Awpm+k+yLnatGZqlkvqZVlDQ9opLw9eMKLYusMrdESryoVwhtdMqQFI4RG1v3Eyg+f4zXV+s55pnsmq5Vlju+X2jatdH1gaGTIMx+4xlaXc5VDcTJjMK8sZa2itNQunyio+uiSdn1M0oe+NFfl3Gaz+cXEQb3yif3FwoL9uq+OSblxyuhMZ494peVk9eYonzAYDDqd325g+PsE9K1RWZaXLVt2+fHY2Njk5OSwsLBz5y5Wa5eXl1+e5O69917twXvvvfftt99+/fXX7iN1CYJgNpuPHj0KQJIkj1SqMcb8pY6Qc+7bRNg7GCtSMH8vHllrGtYOT9+IYH3DIz0bqtqpV2XhSVPnvODgYPym01ra28JjHFXlTNJz2ckEEeCcq4IoqbKT6QzcYWOSHrKTiwLjnHMuBJlCM7rWrr4JRnjElc5/eTCW9krnPOsvG4M755mCgxEcbO/ax7F9A9MHKRXFTBSrZzwVctsDxk43XvLeiIul9Ep8m2pDEGSZc1WQDBzc2OnGYItFVVVRFP2ojlAVDSsOYt5uFFZjbEes641os9TS/qkUBIHqCD2oZf2/62UGg+EK6zzT0tLc14tVVVW//vprWlpaY4MZYxaLxWazXWFAWJgXuG5mkgAAHrhJREFU+wmRSwkMYzri1jRM34SBc/BSHwxNb/YPDbllbMgtY6/tvUrJeXCu9c/jiuv6T1UdAOC0u1+C7FqEo1qrlLIiKSbpmqMNG/PnsDF/dj81pHWOf3VR0YcvKOVFaukFhavVW9YYO93Y2NvlkkJud/38q46a6Kff1SemXnMwPnGwhH2+V1x5GDnxeDIX/ZJpa+xA4QfXE74yYsSIU6dOLV++nHP+97//vVu3bu3atQOwYMGCDz/8EEBJScn69esdDofT6fznP/+5f//+fv36+ThockVhQfh/A/HuELy5FQ+uwNkqXwfUOMvgMfrkLGPnXvo2GUyUmCCCMabTAww6AwDtMRNFJjAmCMxodjde96DgPnfoU7KMXfvoU7IsfUdcYaS+dXtTt36Gdt0M6TfoUzud//sTRR++cIXxLYdNxhcFGLUQE1dKYUH4cixmDsOAFMqCASSgrwivzGw2//vf/37kkUfGjh3boUOHOXPmaMcPHjyo3TK12+1/+tOfDhw4IElSRkbGkiVLLl9TSlqgnHisHoP3f8Zt8/DUjRjbqSU2BDDnDtK3bieFRVt3by47sV87WFv5br/42FVrz1FTrVSVSUEenooLysgOymjSomim04ePn6I9Lv38TceR3fbDu1t4+cShEszbjaUHcEMMHsnGTQlOAdxA9RCBJ6AXyzSRqqpXnoq76gDaa7RZWzpcs0MleOZrGHV4/WYkhgAtKdTzb012HC9gOj13OoxdektRSZAdjhMH7Ef3MFHPFYer4zwYGEzd+hvaZpnzbvN11C5ySWHVhsVB7bsFZfVogXuNOhSsPoS5e3CiDPdkYUxHVzn85XuNtli016hn0RXh1V012fhFNiKXSw/HF/dg5i8Y/m883QtjOvo6oDpUayUAKDIAQ0rH4L53ACiZMx21u5/Vbq7GwSFaWmmzg0rJ+Zp9P0qRcUrZBSG4FXfYTF37er+GQQqPaTXyUS9/aFMcLcW8PVhcgI7R+ENXDEyBRH93CSVCEuBEhoe7YUAyJq/FmiN4qSdrGReEiHx4mv3ILjE8Rq0oNXa5STvo2tvFVWV/scdE5YbFld8tjXvxk+JPX3UcL3DVVzAGzpkgut8esJwK1hzF3N04VIx7srBsNJL8ew9U4mGUCAlBWjiW3IN3fsTdy8x/HYAhja4O9h4pMk6KrL+3reBaJiNxu8wEkWvZDhxgTJDKv5zDa6oBMFHHVbuWCK2/fCeXFFoG3OWDP0ML8GsF5u3Bgr1Ij8C4Trg1lS4BSQPoh4IQAJAETO6Jd26u+X+b8Mw6VDt9HVBDtFYPghQU+cTrXJEBgGsbfnIuO6xb1zrPnwKgS0gJHz9FK7qv2fmf8uX/cp4+6tPAvU3l+OYYHliGYf+GXcaCu/D5SNyeTlmQNIx+Lgi5qFOUsnosGHDbPOwq9HU0lzGk3wDGDJndgtp2FBPTmU4nmEMFo5npg6TQcAiiLiIOjAVldjek3SAYgpggMCYwfVDJ/Lcu7hF6XSuyYsZP6P0x3vkRt7fDlgfxQh+0pQpeckW0atQbaNVoC1mKeVXuUFcfwtQNeLgbHu7WwurJVAWCCC1UswlMcO3ELYiul1QFgug4eeD83/90yRsFIfGNFdp7vRqvt1aN/ngan+3GxhMYkob7OiMr6upvqYdWjQYsmiMkpAFD09ElFk9+hU0n8eYtiGw5O2XWzWTaY/eiUNc23CIAsVUUMxi508EACAyKIobHej8LekG1E0v349NdkFXc1xl/6w+LHyQy0rJQIiSkYfEWzL8Lb23B0Hl4YzD6tPZ1QE3AFVkuPCWFRduP7eH2GmjrSrWeS6XnoSpcdsolhbrY62Hnh6Ol+GQnlh1Az0S82Ae9klrixgjEL1AiJKRRIsNTNyIvCZPWYGQm/tyzpa+2KPnk1ZpdmwSDSbVbIYhw1RoK4Cozh4AJ59+c5Dx7PHTYRMvAe3wc67XSFsJ8shP7izC6I74chzhf7uhOrgeUCAm5ip6JWDUWT63FPYswYwjiW/B0p1xSCEB12gCAq646Q6YCgL0GqqpUlABQyot9FuLvUGbD/L34dBeiTHjgBtyWDt11eK+X+AAlQkKuLsKIj0fgX9sx7N94ZQBuaaltFZjAADAwjjrN6zkDOBcEMBb16Kv24/tMOQN8GOQ1KCjC7J348hAGtcX7Q9GZ+uISj6JESEiTMOChbsiJx5NfYdMpPH8TfL85M+eVG5dwaxVUhZnMSkUZd9gAcG35DGNaLtT+V5B0YEyXmKrzn+5ICsfXR/DxDhwvR34nrB+PiJazaolcRygREvIbdI3F6jF49hvcMR8zhiDVpwVq9mP7ypd+eMkhQQDAVKXuFaFWIqXWVIOrYD7P3k1Sbsfne/DpTsRZMKEL7QhDmhclQkJ+G4sB7w3F53tw90JMycM9Wd4OoHrrWutPX6umkJrKUibpuKICKhMlLjuZpOMOOyQ9nA4milxVATBR5IpTDI3wi/KJg8WYvRMrD2JQW/zzdnSK9nVAJABQIiTkWozpiJx4PPElNp7AqwMR4sXatcq18+Tic/UOctkJd5NCWetrL9e+pAKQS8+7i/FbIJVj/XHM2oGDxbivM90FJV5FtxsIuUbp4Vg2GlFm3DoXW05773PNvW6TIhMEoxmCAEliogRBYDoDBEHQB4ExQRcEJjCdDkxkgsh0ejBBimihBfVVDszagf6f4u2tuDsTmyfgyVzKgsSr6IqQkGtnEPGXvuiXjCe/xMhMPNXTGwv6LQPvNucNPTNlFACoqjYTyFU7ANVhA+eqtmTGqUKbKFQVAHJxYUu7Ijxehk92Ysl+9G6NNwejW/1mG4R4CV0REvJ79WuDr8bhaCmG/RsFRd74REEfxEwWQNtQjQEMogRwJuoAMEnneklgQZndDamdAIghYS0kC3LgPycxcTlGLoRJh6/GYcYQyoLEl+iKkBAPCDfiw9uxqADjlmDCDXg0pxlXOSoVpfYD22GvAVxXewCgKACDKsM9O6gqAEzdBzpOHLAf2a3WVENV4dNd2qudWFyA2TuhEzChC94biiD6F4i0APRjSIjH3JWJvCRM+QYj5uP1m9HhtzdAaIrif/3FcfKA1LajMTmj8tsvXH3qBUAFZwKg6pLSTV37ipZQbrebuvQJysgRQyMMKZk+zILHyzBnF74oQM9E/G0Aeib4KhBCGkCJkBBPigvGJyOwqAD5S3FvBzzZA0ZP/yVjkgRACI009Rhcuf4L1z5qnAGciRJXZCk8xtJ/lHu8YAr2VYd6lWPDCTbrl6B9xbi3A1aPbdEb1JGARYmQEM+7KxP92uB/v8Pgz/ByXwxI8eTJI/7wsuPkAUd0Mi8vrLOPmho27ml9SgflwhltUtC3SmqwcB8+242wIHZvhjxzhOj7jXgIaQQlQkKaRaQJ/7gV/zmJFzdg3h680AdtQj1zZsEUHJSR7aysFMNjBJOFO+1QFGYOqfl5vfPYPrn0AoCgzBzPfNhvt+0MPtuNb49hcCpmDEGnKLWmRjaI1CSQtFyUCAlpRje1xtpx+OgX3DEf93TAf3X3ZNtYMTQi7i+fgatcUcoWv2vdtl7bV1S1VXs/EZbbsbgA8/ZAUTG2E17uh1ADAKiqlwMh5DejREhI89KJeCwHd3fA65vR71M8moP7Ontsw26mNwBggKlrX/vhPYwJcvkFqVXzrNJpiMqx+RQW7MP64xiQgmn9aSEM8T+UCAnxhigTXrsZB4vx+mbM/AWPd8e9HTxZfR+U1TO6dfuid6dAVeWyCx47b+OOlWFxAb4oQJgR93bAtP6uS0BC/A4lQkK8p10EPhqGHefw1la8+xP+0BWjO8Ks88CZq75bVrb4fWYMBiBYWnngjI0osmLlISzdj9OVGN4OM4cjM7L5Po0Qb6BESIi3dYnF7BHYcx7vb8OMn3BPB4y/AQm/r67AeeYYAG63AuA11R6Js66SGqw5glWHsLMQN6dgUk/c1Boi8/jnEOIDlAgJ8Y2O0Xh3KE5V4JOduP1zdI3F6I4YkHyNW9KEDL1fbBUphscoxWdNOQM9FeSpCqw7ijVHsOcC+rXBuE741zDaDoZcbxh31yGRZlNRUZGUlFReXu7Bc1ZXVxuNRsGnO2Y1UWVlpcXiH3XUvgrVJmPlISzYi8OluC0dw9KREw/hitdbzReqXcG2M9h4AuuPo6QGA1MwuC1uanONC3xUVa2pqTGbzZ4O0/McDgfn3GDwg6lOq9VqMBhEkWozPYN+tSPE94Ik3JWJuzJxqgLLDuDFDbhgxcAUDEhGryRvNDu0ydhZiB9PY8tp/HIOGRHo2wZvDEKn6KvkY0KuA5QICWlBkkLwX93xX91d9yQ/34s/f420MOTEo2ssbohBUig8kphqZBwqxr4L2HMBuwpxsBgZkegej4ld0CMBwXpPfAYhfoISISEtUVIIJnTBhC5wKthRiG1nsOIgXvkelQ6khyMtDDFB+tQoxFkQYUSrIIQaoL/sPplNRqUDZTYU16CwCueq8GsFjpfhWBkuWJEahsxIdIzGnRnoGO2x0kZC/A4lQkJaNJ2I7vHoHu96WmbDoRIcKcHhIrbxBM5UosiKMjsq7XAosBhcLUZljmoHDCKCDWhlQIQJccGINiMtHANSkNIKSaG05pMQF0qEhPiTVkGuvFhZabdY6t/BrLC7elFIDGa6vUlI01AiJOT64YVlNYRcf/xg8T0hhBDSfCgREkIICWiUCAkhhAQ0SoSEEEICGiVCQgghAY0SISGEkIBGiZAQQkhAo0RICCEkoFEiJIQQEtAoERJCCAlolAh/L1VVS0tLfR0FIYSQa0SJsFF79+4dNWpUcnJyenp6Y2O+/vrrxMTEzMzMtm3bbt261ZvhEUII8QhKhI1ijA0dOnTq1KllZWUNDrDb7fn5+TNmzDh37tyUKVPGjx/POfdykIQQQn4nSoSN6tChw4MPPpiRkdHYgDVr1gQHB48cORLAxIkTi4qK6KKQEEL8DiXCa3fkyJHMzEztsSRJqampR44caWww5/zo0aNHjx49ceKEqqreipEQQshVBHQ/wkOHDs2dO/fy45MmTWrVqtVV315eXm4ymdxPLRZLYzdRVVWtrq4eOHCg9vTtt9/u37//NYV8kdVqlWVZEPzgV5mqqipfh9BUFKrHqapqs9n84pc/h8PBOXc4HL4O5OpqamocDocoih48Z1BQkE6n8+AJ/UhAJ0JBECSpgW+AMdaUt0dFRZWXl7uflpaWRkdHN/ZBwcHBx44du7Y4Gzun0Wj0i0QIwGKx+DqEpqJQPUtVVUmSzGazrwO5Oi0RGgx+0N1YFEWDweDZRBjIAjoRpqamTp069ZrfnpWV9fLLLyuKIopidXX1/v37O3bs6MHwCCGEeIF/XE/4hNVqXbdu3bZt25xO57p163744Qft+IMPPrh06VIAffv2jYqKevHFF0+cOPHf//3fubm57ilDQggh/oISYaNKS0unT5++atWq7t27T58+febMmdpxs9ms1+sBMMaWL1++b9++W265paSk5PPPP/dpvIQQQq4Fo9I3L6ioqEhKSqo7ofj7VVdX+8scYWVlpV/MZoFCbQaqqtbU1NAcoWdZrVaaI/QgP/hnlBBCCGk+lAgJIYQENEqEhBBCAholQkIIIQGNEiEhhJCARomQEEJIQKNESAghJKBRIiSEEBLQKBESQggJaJQICSGEBDRKhIQQQgIaJUJCCCEBjRIhIYSQgEaJkBBCSECjREgIISSgUSIkhBAS0CgREkIICWiUCAkhhAQ0SoSEEEICGiVCQgghAY0SISGEkIBGiZAQQkhAo0RICCEkoFEiJIQQEtAoERJCCAlolAgJIYQENEqEhBBCAholQkIIIQGNEiEhhJCARomQEEJIQKNESAghJKBRIiSEEBLQKBESQggJaJQICSGEBDRKhIQQQgIaJUJCCCEBjRIhIYSQgEaJkBBCSECjREgIISSgUSIkhBAS0CgREkIICWiUCAkhhAQ0SoSEEEICGiVCQgghAY0SISGEkIBGiZAQQkhAk3wdQEvndDqrqqpCQkJEUbz81crKSlmWtceiKIaEhHg3OkIIIb8XXRE2qrq6ukePHhaLJTw8vKCgoMExgwcP7tChQ05OTk5Ozrhx47wcISGEkN+PrggbpdPppk2blp2dHRMTc4VhM2fOHDp0qNeiIoQQ4ll0RdgovV4/ePDgiIiIKw+rqKg4efKkoijeiYoQQohn0RXh7/XMM89IklRaWvrmm29OmDChsWGKoqxbt0573L1799DQUG8FSAgh5EoCOhHa7fbx48dffvzRRx/t169fU86wbNmy6OhoAGvXrh0xYkTPnj0zMzMvH6aqqt1uf+WVV7Snzz//fI8ePa49bgCA1WpVFEUQ/OCavrq6mjHm6yiahEL1OFVVbTYb59zXgVydw+HgnDudTl8HcnVWq9XpdDa4gu+aGQwGnU7nwRP6kYBOhJIk3XPPPZcfT0lJaeIZtCwIYPDgwV26dNm8eXODiVAQBJPJ9O23315zqJdjjBmNRr9IhJzz4OBgX0fRJBSqx6mqKoqi2Wz2dSBXpyVCg8Hg60CuThAEg8Hg2UQYyAI6EYqiOGrUKI+cyul0njlzJjw83CNnI4QQ4jUBnQiv6t13362qquKcz5o1KyYm5oknnjCZTFOnTj179uzMmTNPnTo1ffr03r17S5L08ccfG43GW265xdchE0II+W384MaaD5WXl5eWlj7zzDN6vb60tFSb58jNze3fvz+AVq1aRUVFLV26dOHChXl5eVu2bDGZTF6LbeHChUePHvXax/0eH3zwQUVFha+jaJLXXnvN1yE0SUVFxQcffODrKJrkyJEjCxcu9HUUTbJp06bvvvvO11E0yeLFiw8cOODrKK4fzC8msf1dRUVFUlJSeXm5B885YsSI8ePHe+rWbrPKyMhYsmRJg7OnLQ1j/vE3Yt++faNGjWpsn4cWZdGiRZ999tnSpUt9HcjV/eUvf3E6nX/72998HcjV3XvvvcOGDcvPz/d1INcJuiIkhBAS0CgREkIICWiUCAkhhAQ0/5gR8XdVVVVhYWGtW7f24DnPnz8fHBzszeU51+zXX3+NiYnxi1rd48ePJycn+zqKq3M6nYWFhYmJib4O5OqsVmtVVZW74rYlKysr45yHhYX5OpCru3Dhgslk8mx15siRI19//XUPntCPUCL0khMnTnh2P1KHw6HT6fxibxG73e4XRcqgUJuBtleLXq/3dSBXp/0N9Ysq9eb46x8bG+sXv1g3B0qEhBBCAhrNERJCCAlolAgJIYQENEqEhBBCAholQkIIIQGNNt32Mw6HY9euXbt37w4LC7vjjjsuH1BWVrZgwQL30169enXs2NGLAV4Syfbt2w8fPpydnZ2dnd3gmIMHD86ZM0eW5bFjx3bq1MnLEda1YsWK9evXJyQkPPTQQyEhIfVe/eWXX3766Sf303Hjxnmzr9CyZcs2btyYkJDw8MMPWyyWywfs3bt37ty5giDk5+dnZGR4LbDLLVq0aPPmza1bt37ooYcu/4q2bt26c+dO99MHHnjAJ6tJZVnes2fPrl279Hr96NGjGxxjs9k++uijY8eOde/effTo0b5anu10Ovfs2bNz506z2Xz33XdfPqCqqmrevHnup7m5uV26dPFigNcJuiL0M+++++7o0aP/8Y9/vPrqqw0OOHv27J///OejtXy42/W4ceOefvrpv/71rytWrGhwwJEjR3r06KGqqsVi6d27944dO7wcods777zz5JNPpqambtmypX///pcXuqxateqDDz5wf6uerYS5sjfffHPy5MmpqambN28eOHCgqqr1Buzdu7dXr15BQUGSJPXs2dOHezG/8sorzz//fFpa2jfffDNkyJDLByxZsmTWrFnur9FXS9bnzZs3YsSIGTNmPP/8842NufPOO1esWJGenv7KK69MnTrVm+HVNWvWrJEjR86YMePll19ucEBxcfETTzzh/krLysq8HOF1ghO/oigK5/yTTz7Jzc1tcMC+fftiYmK8G1TDtFDHjBnz0ksvNThg0qRJEydO1B5PmTIlPz/fa7HV5XQ6ExMT165dyzmXZTk1NXXlypX1xkybNu2xxx7zfmwOhyMuLu7bb7/V4kxOTv7qq6/qjXnwwQcnTZqkPX788ccfffRRb0fJOee8pqYmIiJiy5YtnHO73R4bG7tx48Z6Y5599tlnn33WF9FdQvvJXLVqVdu2bRsc8PPPP4eGhlqtVs75nj17LBZLRUWFV0OspYW6cOHCrKysBgccP37cYrF4N6jrEF0R+pmmtKS32WxvvfXW+++/79tGLVcNdePGjYMHD9YeDxo0aOPGjc0fVAOOHDlSWFiotdYSRXHAgAENRrJ///7p06fPmTOnsrLSa7EdPHiwpKSkT58+ACRJ6t+//+Wxbdy4cdCgQdpjH36Ne/bskWU5NzcXgF6v79u3b4OR7Nq1a/r06Z9//rnVavV6jC5N+cns3bu30WgEkJWVFRISsn37dq+EVl9T/r7Lsvz222+/++67+/bt80JI1yVKhNcbnU7Xp0+foqKirVu3Zmdnz58/39cRNers2bNRUVHa4+jo6HPnznFf3Cs7d+5cWFiYJLnmy2NiYs6cOVNvTFRUVEpKSmVl5cyZMzt06HD69GmvxRYREeHe66TB2Op9jWfPnvVObPWcO3cuKirKPZfWYKixsbFJSUkVFRUzZszo1KlTUVGR18NsEu3P4n4aHR19+Z+lhdB+Pbpw4cL27dt79Ogxe/ZsX0fkl2ixTIvz3nvvPfnkk/UOMsacTmdT3p6WlrZ8+XLtcb9+/Z5++ul7773XwyHWGj58+OrVq+sdHDJkSGOTgvXodDpZlrXHsixLktR8SxJuvvnmDRs21Ds4atSo+fPnS5LkDgOA0+m8fOuyRx555JFHHtEeDxs27PXXX3/rrbeaKdS6mhJb3TGyLPtqM7OmhDpp0iTtAee8f//+b7/99rRp07wXYpNJklR3GrglbxGXkJCwatUq7fHgwYMff/zx+++/3y92XmxR6IqwxXnsscfkyzQxC9bTq1ev06dPOxwOjwepWb58+eWhNjELAkhISHD/on369OmEhIRmihPAunXrLg9Vu1yOj48vKyurrq52RxIXF3eFU+Xl5R09erT5Qq0rPj6+pKSkpqZGe9pgbPW+xvj4eO/EVk98fPz58+fdP6hX/hoZY7169fLa1/hbJSQkuC/6VVU9e/asr77V3yQvL6+4uNizDcADBCXC68R//vOfkpISADabzX1QW/bWon6ZraioWL9+vfZ42LBhCxcu1B4vXLhw2LBhPgkpJSUlKytr8eLFWnhr164dPnw4gNLSUvcsl/tblWV59erVXqtISUtLS09PX7JkCYCysrKvv/5ai62kpOS7777TxgwfPrwlfI0dO3aMiYnRrk6Kioo2bNigRVJUVLRp0yZtjPtrtNvta9asycrK8kmojdmyZUthYSGAoUOH/vDDD9qvF+vXr9fr9Tk5Ob6O7hKbNm26cOECAPcvSQBWrFiRmJjYqlUr38Xlt3y9Wof8Nps3b87Ozk5OTjabzdnZ2e7lgqGhoV9++SXn/LnnnuvevXt+fn7fvn0jIiLWrVvnq1DfeOON7Ozs8PDwuLi47OzshQsXcs61fxO1AcXFxe3btx88ePAdd9yRlJR06tQpX4W6atWqyMjI+++/Pysra8yYMdrBdevWmUwm7XGXLl1uvfXW/Pz8tLS07Ozs0tJSr8W2fPnyyMjIBx54oEOHDvfdd5928KuvvnKvFTxz5kxycvLtt98+dOjQtLS0wsJCr8VWz4IFC7RQ27dv//DDD2sHlyxZ4l7GnJ6ePnTo0Pz8/OTk5Ly8vKqqKp/EuW/fvuzs7LS0NIPBkJ2d/cADD2jHU1NT58yZoz2ePHly27ZtJ0yYEB0dPXv2bJ/EyTnfvn17dnZ227ZtjUZjdnb2H//4R+14XFzcokWLOOfTpk3r1q1bfn5+//79w8LCVq1a5atQ/Rp1n/AzFRUVhw4dcj8NDQ1NS0sDsH379tTUVG3N908//XTmzJmIiIgePXqEhob6KtRTp06dP3/e/bR169ZRUVFVVVUFBQXdu3fXDlqt1m+++UaW5ZtvvrnBUnGvOXny5KZNmxISEm666SZtikX7qrWtAM6dO7dt27bKysqUlJTc3NymrOXzoBMnTmzevDkxMbF3796Xxwagqqpq3bp1jLGbb77Zm5X+lzty5MiPP/7YunXrvLw87UhZWdnx48e1Ku8zZ85s27bNarWmpqbm5OT4airLarUWFBS4n5rNZm0Xgl27diUkJERERGjHt27devTo0ezs7Hbt2vkkTgBVVVV1135bLBYtmB07drRp0yYsLMxms/3000+//vpreHh4bm6uXzRTbIEoERJCCAloNEdICCEkoFEiJIQQEtAoERJCCAlolAgJIYQENEqEhBBCAholQkIIIQGNEiEhhJCARomQEEJIQKNESAghJKBRIiSEEBLQKBESQggJaP8foJG1P51X92wAAAAASUVORK5CYII=", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 13 + } + ], + "cell_type": "code", + "source": [ + "julia_plot(value(model[:v]), c)" + ], + "metadata": {}, + "execution_count": 13 + }, + { + "cell_type": "markdown", + "source": [ + "Let's now look at degree 4." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "* Solver : CSDP\n\n* Status\n Result count : 1\n Termination status : ALMOST_OPTIMAL\n Message from the solver:\n \"Problem solved to near optimality.\"\n\n* Candidate solution (result #1)\n Primal status : NEARLY_FEASIBLE_POINT\n Dual status : NEARLY_FEASIBLE_POINT\n Objective value : 5.03758e+00\n Dual objective value : 5.04107e+00\n\n* Work counters\n Solve time (sec) : 4.04534e-01\n" + }, + "metadata": {}, + "execution_count": 14 + } + ], + "cell_type": "code", + "source": [ + "model = outer_approximation(solver, 4, c)\n", + "solution_summary(model)" + ], + "metadata": {}, + "execution_count": 14 + }, + { + "cell_type": "markdown", + "source": [ + "We visualize below:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: Skipped marker arg pixel.\n", + "└ @ Plots ~/.julia/packages/Plots/ju9dp/src/args.jl:1149\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=2}", + "image/png": "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8+z333+/devWwMNbb701mHWFli1btn79+rS0tLvuusvpdJ7fYPfu3e+++64gCHl5ed27dw9aYOf7+OOPN23a1KFDhzvvvPP8j2jLli0//vhj4OFtt90WktGkmqbt2rVrx44dFotlypQpdbbxer1vvvnm4cOH+/fvP2XKlFANz1ZVddeuXT/++KPdbr/pppvOb+Byud57773Aw9zc3D59+gQxwF8I6hG2Ma+88sqUKVNeeumlZ555ps4GJ0+evP/++w9VC+Fq17feeusDDzzwl7/85dNPP62zwcGDBwcMGGAYhtPpHDp06A8//BDkCAP+/ve///73v8/MzNy8efOoUaPOn+iyYsWK119/PfCpNu9MmAt7/vnnZ8+enZmZuWnTpjFjxhiGcU6D3bt3Dx48OCIiQpKkgQMHhnAt5qeffvqRRx7Jysr66quvrrnmmvMbLFmyZMGCBYGPMVRD1t97771Jkya9/PLLjzzySH1tfvWrX3366addunR5+umn586dG8zwaluwYMENN9zw8ssv//nPf66zQXFx8X333Rf4SMvKyoIc4S8EJ22Kruuc87fffjs3N7fOBvn5+cnJycENqm5mqFOnTn388cfrbDBr1qyZM2ea23PmzMnLywtabLWpqpqenr5q1SrOuaZpmZmZn3322Tltnnzyyd/97nfBj01RlNTU1K+//tqMMyMj48svvzynzR133DFr1ixz+957773nnnuCHSXnnHOPxxMfH79582bOuc/nS0lJWb9+/TltHnrooYceeigU0Z3F/M1csWJF586d62zw3XffRUdHu91uzvmuXbucTmdFRUVQQ6xmhrp48eLs7Ow6Gxw5csTpdAY3qF8g6hG2MQ0pSe/1el944YXXXnsttIVaLhrq+vXrx40bZ26PHTt2/fr1LR9UHQ4ePFhYWGiW1hJFcfTo0XVGsnfv3nnz5i1atKiysjJose3fv7+kpGT48OEAJEkaNWrU+bGtX79+7Nix5nYIP8Zdu3ZpmpabmwvAYrGMGDGizkh27Ngxb968999/3+12Bz1Gv4b8Zg4dOjQyMhJAdnZ2VFTU9u3bgxLauRry913TtBdffPGVV17Jz88PQki/SJQIf2lkWR4+fHhRUdGWLVtycnI+/PDDUEdUr5MnTyYmJprbSUlJp06d4qG4Vnbq1KnY2FhJ8t8vT05OLigoOKdNYmJip06dKisr58+f37NnzxMnTgQttvj4+MBaJ3XGds7HePLkyeDEdo5Tp04lJiYG7qXVGWpKSkr79u0rKipefvnl3r17FxUVBT3MBjHfS+BhUlLS+e+llTC/Hp05c2b79u0DBgxYuHBhqCNqk2iwTKvz6quv/v73vz9nJ2NMVdWGvDwrK2v58uXm9siRIx944IFbbrmlmUOsNnHixM8///ycnddcc019NwXPIcuypmnmtqZpkiS13JCEK6+8ct26defsnDx58ocffihJUiAMAKqqnr902d1333333Xeb2xMmTHjuuedeeOGFFgq1tobEVruNpmmhWsysIaHOmjXL3OCcjxo16sUXX3zyySeDF2KDSZJU+zZwa14iLi0tbcWKFeb2uHHj7r333hkzZrSJlRdbFeoRtjq/+93vtPM0MAueY/DgwSdOnFAUpdmDNC1fvvz8UBuYBQGkpaUFvmifOHEiLS2theIEsGbNmvNDNbvL7dq1Kysrq6qqCkSSmpp6gUMNGTLk0KFDLRdqbe3atSspKfF4PObDOmM752Ns165dcGI7R7t27U6fPh34Rb3wx8gYGzx4cNA+xkuVlpYW6PQbhnHy5MlQfaqXZMiQIcXFxc1bADxMUCL8hfj3v/9dUlICwOv1Bnaaw95a1ZfZioqKtWvXmtsTJkxYvHixub148eIJEyaEJKROnTplZ2d/8sknZnirVq2aOHEigNLS0sBdrsCnqmna559/HrQZKVlZWV26dFmyZAmAsrKy1atXm7GVlJRs2LDBbDNx4sTW8DH26tUrOTnZ7J0UFRWtW7fOjKSoqGjjxo1mm8DH6PP5Vq5cmZ2dHZJQ67N58+bCwkIA48eP/+abb8yvF2vXrrVYLP369Qt1dGfZuHHjmTNnAAS+JAH49NNP09PTY2JiQhdXmxXq0Trk0mzatCknJycjI8Nut+fk5ASGC0ZHR3/xxRec84cffrh///55eXkjRoyIj49fs2ZNqEL961//mpOTExcXl5qampOTs3jxYs65+W+i2aC4uLhbt27jxo27/vrr27dvf/z48VCFumLFioSEhBkzZmRnZ0+dOtXcuWbNGpvNZm736dPn6quvzsvLy8rKysnJKS0tDVpsy5cvT0hIuO2223r27PnrX//a3Pnll18GxgoWFBRkZGRcd91148ePz8rKKiwsDFps5/joo4/MULt163bXXXeZO5csWRIYxtylS5fx48fn5eVlZGQMGTLE5XKFJM78/PycnJysrCyr1ZqTk3PbbbeZ+zMzMxctWmRuz549u3PnzrfffntSUtLChQtDEifnfPv27Tk5OZ07d46MjMzJyfntb39r7k9NTf344485508++WTfvn3z8vJGjRoVGxu7YsWKUIXaplH1iTamoqLip59+CjyMjo7OysoCsH379szMTHPM99atWwsKCuLj4wcMGBAdHR2qUI8fP3769OnAww4dOiQmJrpcrj179vTv39/c6Xa7v/rqK03TrrzyyjqnigfNsWPHNm7cmJaWNmzYMPMWi/lRm0sBnDp1atu2bZWVlZ06dcrNzW3IWL5mdPTo0U2bNqWnpw8dOvT82AC4XK41a9Ywxq688spgzvQ/38GDB7/99tsOHToMGTLE3FNWVnbkyBFzlndBQcG2bdvcbndmZma/fv1CdSvL7Xbv2bMn8NBut5urEOzYsSMtLS0+Pt7cv2XLlkOHDuXk5HTt2jUkcQJwuVy1x347nU4zmB9++KFjx46xsbFer3fr1q0///xzXFxcbm5umyim2ApRIiSEEBLW6B4hIYSQsEaJkBBCSFijREgIISSsUSIkhBAS1igREkIICWuUCAkhhIQ1SoSEEELCGiVCQgghYY0SISGEkLBGiZAQQkhYo0RICCEkrP1/IWBlbhUqxX0AAAAASUVORK5CYII=", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 15 + } + ], + "cell_type": "code", + "source": [ + "julia_plot(value(model[:v]), c)" + ], + "metadata": {}, + "execution_count": 15 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Systems and Control/julia_set.jl b/previews/PR347/generated/Systems and Control/julia_set.jl new file mode 100644 index 000000000..419e70936 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set.jl @@ -0,0 +1,104 @@ +function julia_map(point, c) + a, b = point + return [a^2 - b^2 + real(c), 2a * b + imag(c)] +end + +escape_radius(c) = (1 + √(1 + 4 * abs(c))) / 2 + +using LinearAlgebra +function in_set(x, c, m=2000) + r = escape_radius(c) + for i in 1:m + if norm(x) > r + return false + end + x = julia_map(x, c) + end + return true +end + +using SpecialFunctions +using DynamicPolynomials +β(α) = (α + 1) / 2 +function circle_integral(mono::AbstractMonomial) + if any(isodd, exponents(mono)) + return 0.0 + else + return 2 * prod(gamma ∘ β, exponents(mono)) / gamma(sum(β, exponents(mono))) + end +end +function disk_integral(mono::AbstractMonomial, r) + d = degree(mono) + nvariables(mono) + return circle_integral(mono) * r^d / d +end +function disk_integral(p::AbstractPolynomialLike, r) + return sum(MultivariatePolynomials.coefficient(t) * disk_integral(monomial(t), r) for t in terms(p)) +end + +using SumOfSquares +function outer_approximation(solver, d::Int, c; α = 1/2) + @polyvar x[1:2] + model = SOSModel(solver) + r = escape_radius(c) + S = @set sum(x.^2) <= r^2 + @variable(model, v, Poly(monomials(x, 0:2d))) + @variable(model, w0, SOSPoly(monomials(x, 0:d))) + @variable(model, w1, SOSPoly(monomials(x, 0:(d - 1)))) + @constraint(model, α * v(x => julia_map(x, c)) <= v, domain = S) + w = w0 + w1 * (r^2 - sum(x.^2)) + @constraint(model, w >= v + 1, domain = S) + @objective(model, Min, disk_integral(w, r)) + optimize!(model) + if primal_status(model) == MOI.NO_SOLUTION + return + end + return model +end + +using ImplicitPlots +using Plots +function julia_plot(poly, c, n=200, m=1000; tol=1e-6, res = 1000) + r = escape_radius(c) + p = implicit_plot(poly; xlims=(-r, r) .* 1.1, ylims=(-r, r), resolution = res, label="") + θ = range(0, stop=2π, length=100) + points = Vector{Float64}[] + as = range(-r, r, length=n) + bs = range(-r, r, length=n) + for a in as, b in bs + point = [a, b] + if in_set(point, c, m) + push!(points, point) + end + end + xs = [point[1] for point in points] + ys = [point[2] for point in points] + scatter!(p, xs, ys, label="", markerstrokewidth=0, markersize=1.5, m=:pixel) + return p +end + +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + +c = -0.7 + 0.2im +model = outer_approximation(solver, 2, c) +solution_summary(model) + +julia_plot(value(model[:v]), c) + +model = outer_approximation(solver, 4, c) +solution_summary(model) + +julia_plot(value(model[:v]), c) + +c = -0.9 + 0.2im +model = outer_approximation(solver, 2, c) +solution_summary(model) + +julia_plot(value(model[:v]), c) + +model = outer_approximation(solver, 4, c) +solution_summary(model) + +julia_plot(value(model[:v]), c) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Systems and Control/julia_set/35f3984b.svg b/previews/PR347/generated/Systems and Control/julia_set/35f3984b.svg new file mode 100644 index 000000000..98d69efee --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set/35f3984b.svg @@ -0,0 +1,9139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/julia_set/ade489a8.svg b/previews/PR347/generated/Systems and Control/julia_set/ade489a8.svg new file mode 100644 index 000000000..0ada88a47 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set/ade489a8.svg @@ -0,0 +1,5025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/julia_set/de683ec8.svg b/previews/PR347/generated/Systems and Control/julia_set/de683ec8.svg new file mode 100644 index 000000000..188eeb6dc --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set/de683ec8.svg @@ -0,0 +1,9139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/julia_set/f243735d.svg b/previews/PR347/generated/Systems and Control/julia_set/f243735d.svg new file mode 100644 index 000000000..d37eae171 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set/f243735d.svg @@ -0,0 +1,5025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/julia_set/index.html b/previews/PR347/generated/Systems and Control/julia_set/index.html new file mode 100644 index 000000000..e8f6b5c1d --- /dev/null +++ b/previews/PR347/generated/Systems and Control/julia_set/index.html @@ -0,0 +1,139 @@ + +Outer approximation of Julia set · SumOfSquares

Outer approximation of Julia set

Adapted from: Section 7.1.3 of [KHJ14]

[KHJ14] Milan Korda, Didier Henrion, and Colin N. Jones. Convex computation of the maximum controlled invariant set for polynomial control systems. SIAM Journal on Control and Optimization 52.5 (2014): 2944-2969.

The Julia map is defined as follows:

function julia_map(point, c)
+    a, b = point
+    return [a^2 - b^2 + real(c), 2a * b + imag(c)]
+end
julia_map (generic function with 1 method)

The *escape radius" is the radius r such that r^2 ≥ r + abs(c). Ouside of the circle of that radius, all points diverge so we know the Julia set belongs to that circle.

escape_radius(c) = (1 + √(1 + 4 * abs(c))) / 2
escape_radius (generic function with 1 method)

To check whether a point is in the Julia set, we can iterate and once the point leaves the circle of escape radius, we consider that it is not in the Julia set, if it stays in the set, we consider that it is in the Julia set. This gives an outer approximation that converges to the Julia set when m increases.

using LinearAlgebra
+function in_set(x, c, m=2000)
+    r = escape_radius(c)
+    for i in 1:m
+        if norm(x) > r
+            return false
+        end
+        x = julia_map(x, c)
+    end
+    return true
+end
in_set (generic function with 2 methods)

To sort of minimize a level set of a polynomial we minimize integral of that polynomial. We borrow the following from https://doi.org/10.1080/00029890.2001.11919774

using SpecialFunctions
+using DynamicPolynomials
+β(α) = (α + 1) / 2
+function circle_integral(mono::AbstractMonomial)
+    if any(isodd, exponents(mono))
+        return 0.0
+    else
+        return 2 * prod(gamma ∘ β, exponents(mono)) / gamma(sum(β, exponents(mono)))
+    end
+end
+function disk_integral(mono::AbstractMonomial, r)
+    d = degree(mono) + nvariables(mono)
+    return circle_integral(mono) * r^d / d
+end
+function disk_integral(p::AbstractPolynomialLike, r)
+    return sum(MultivariatePolynomials.coefficient(t) * disk_integral(monomial(t), r) for t in terms(p))
+end
disk_integral (generic function with 2 methods)

The following function implements [KHJ14, (8)].

using SumOfSquares
+function outer_approximation(solver, d::Int, c; α = 1/2)
+    @polyvar x[1:2]
+    model = SOSModel(solver)
+    r = escape_radius(c)
+    S = @set sum(x.^2) <= r^2
+    @variable(model, v, Poly(monomials(x, 0:2d)))
+    @variable(model, w0, SOSPoly(monomials(x, 0:d)))
+    @variable(model, w1, SOSPoly(monomials(x, 0:(d - 1))))
+    @constraint(model, α * v(x => julia_map(x, c)) <= v, domain = S)
+    w = w0 + w1 * (r^2 - sum(x.^2))
+    @constraint(model, w >= v + 1, domain = S)
+    @objective(model, Min, disk_integral(w, r))
+    optimize!(model)
+    if primal_status(model) == MOI.NO_SOLUTION
+        return
+    end
+    return model
+end
outer_approximation (generic function with 1 method)

The following function plots the Julia set with the outer approximation.

using ImplicitPlots
+using Plots
+function julia_plot(poly, c, n=200, m=1000; tol=1e-6, res = 1000)
+    r = escape_radius(c)
+    p = implicit_plot(poly; xlims=(-r, r) .* 1.1, ylims=(-r, r), resolution = res, label="")
+    θ = range(0, stop=2π, length=100)
+    points = Vector{Float64}[]
+    as = range(-r, r, length=n)
+    bs = range(-r, r, length=n)
+    for a in as, b in bs
+        point = [a, b]
+        if in_set(point, c, m)
+            push!(points, point)
+        end
+    end
+    xs = [point[1] for point in points]
+    ys = [point[2] for point in points]
+    scatter!(p, xs, ys, label="", markerstrokewidth=0, markersize=1.5, m=:pixel)
+    return p
+end
julia_plot (generic function with 3 methods)

We need to pick an SDP solver, see here for a list of the available choices.

import CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
MathOptInterface.OptimizerWithAttributes(CSDP.Optimizer, Pair{MathOptInterface.AbstractOptimizerAttribute, Any}[MathOptInterface.Silent() => true])

Let's start with the value of c corresponding to the left image of [KHJ14, Figure 3] and with degree 2.

c = -0.7 + 0.2im
+model = outer_approximation(solver, 2, c)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 6.02400e+00
+  Dual objective value : 6.02400e+00
+
+* Work counters
+  Solve time (sec)   : 1.52879e-02
+

We visualize below:

julia_plot(value(model[:v]), c)
Example block output

Let's now look at degree 4.

model = outer_approximation(solver, 4, c)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : ALMOST_OPTIMAL
+  Message from the solver:
+  "Problem solved to near optimality."
+
+* Candidate solution (result #1)
+  Primal status      : NEARLY_FEASIBLE_POINT
+  Dual status        : NEARLY_FEASIBLE_POINT
+  Objective value    : 5.03023e+00
+  Dual objective value : 5.03038e+00
+
+* Work counters
+  Solve time (sec)   : 3.72249e-01
+

We visualize below:

julia_plot(value(model[:v]), c)
Example block output

Let's now use the value of c corresponding to the right image of [KHJ14, Figure 3] and with degree 2.

c = -0.9 + 0.2im
+model = outer_approximation(solver, 2, c)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : OPTIMAL
+  Message from the solver:
+  "Problem solved to optimality."
+
+* Candidate solution (result #1)
+  Primal status      : FEASIBLE_POINT
+  Dual status        : FEASIBLE_POINT
+  Objective value    : 6.57446e+00
+  Dual objective value : 6.57446e+00
+
+* Work counters
+  Solve time (sec)   : 1.52218e-02
+

We visualize below:

julia_plot(value(model[:v]), c)
Example block output

Let's now look at degree 4.

model = outer_approximation(solver, 4, c)
+solution_summary(model)
* Solver : CSDP
+
+* Status
+  Result count       : 1
+  Termination status : ALMOST_OPTIMAL
+  Message from the solver:
+  "Problem solved to near optimality."
+
+* Candidate solution (result #1)
+  Primal status      : NEARLY_FEASIBLE_POINT
+  Dual status        : NEARLY_FEASIBLE_POINT
+  Objective value    : 5.03758e+00
+  Dual objective value : 5.04107e+00
+
+* Work counters
+  Solve time (sec)   : 4.10146e-01
+

We visualize below:

julia_plot(value(model[:v]), c)
Example block output

This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Systems and Control/lyapunov_function_search.ipynb b/previews/PR347/generated/Systems and Control/lyapunov_function_search.ipynb new file mode 100644 index 000000000..14a316a02 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/lyapunov_function_search.ipynb @@ -0,0 +1,335 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Lyapunov Function Search" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: SOSTOOLS' SOSDEMO2 (See Section 4.2 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf))" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃],)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:3]" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "We define below the vector field $\\text{d}x/\\text{d}t = f$" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element Vector{MultivariatePolynomials.RationalPoly{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Int64}, DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Int64}}}:\n (-x₁x₃² - x₁³) / (1)\n (-x₂ - x₁²x₂) / (1)\n (-4x₃ - x₃³ + 3x₁²x₃ + 3x₁²x₃³) / (1 + x₃²)" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "f = [-x[1]^3 - x[1] * x[3]^2,\n", + " -x[2] - x[1]^2 * x[2],\n", + " -x[3] - 3x[3] / (x[3]^2 + 1) + 3x[1]^2 * x[3]]" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices.\n", + "We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints." + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "using SumOfSquares\n", + "using CSDP\n", + "solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + "model = SOSModel(solver);" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "We are searching for a Lyapunov function $V(x)$ with monomials $x_1^2$, $x_2^2$ and $x_3^2$.\n", + "We first define the monomials to be used for the Lyapunov function:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "3-element Vector{DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}:\n x₁²\n x₂²\n x₃²" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "monos = x.^2" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We now define the Lyapunov function as a polynomial decision variable with these monomials:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1])x₃² + (_[2])x₂² + (_[3])x₁²", + "text/latex": "$$ ({\\_}_{1})x_{3}^{2} + ({\\_}_{2})x_{2}^{2} + ({\\_}_{3})x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "@variable(model, V, Poly(monos))" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "We need to make sure that the Lyapunov function is strictly positive.\n", + "We can do this with a constraint $V(x) \\ge \\epsilon (x_1^2 + x_2^2 + x_3^2)$,\n", + "let's pick $\\epsilon = 1$:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(_[1] - 1)x₃² + (_[2] - 1)x₂² + (_[3] - 1)x₁² is SOS", + "text/latex": "$$ ({\\_}_{1} - 1)x_{3}^{2} + ({\\_}_{2} - 1)x_{2}^{2} + ({\\_}_{3} - 1)x_{1}^{2} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "@constraint(model, V >= sum(x.^2))" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We now compute $\\text{d}V/\\text{d}x \\cdot f$." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "((-8 _[1])x₃² + (-2 _[2])x₂² + (-2 _[1])x₃⁴ + (-2 _[2])x₂²x₃² + (-2 _[3] + 6 _[1])x₁²x₃² + (-2 _[2])x₁²x₂² + (-2 _[3])x₁⁴ + (-2 _[3] + 6 _[1])x₁²x₃⁴ + (-2 _[2])x₁²x₂²x₃² + (-2 _[3])x₁⁴x₃²) / (1 + x₃²)", + "text/latex": "$$ \\frac{(-8 {\\_}_{1})x_{3}^{2} + (-2 {\\_}_{2})x_{2}^{2} + (-2 {\\_}_{1})x_{3}^{4} + (-2 {\\_}_{2})x_{2}^{2}x_{3}^{2} + (-2 {\\_}_{3} + 6 {\\_}_{1})x_{1}^{2}x_{3}^{2} + (-2 {\\_}_{2})x_{1}^{2}x_{2}^{2} + (-2 {\\_}_{3})x_{1}^{4} + (-2 {\\_}_{3} + 6 {\\_}_{1})x_{1}^{2}x_{3}^{4} + (-2 {\\_}_{2})x_{1}^{2}x_{2}^{2}x_{3}^{2} + (-2 {\\_}_{3})x_{1}^{4}x_{3}^{2}}{1 + x_{3}^{2}} $$" + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "using LinearAlgebra # Needed for `dot`\n", + "dVdt = dot(differentiate(V, x), f)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "The denominator is $x[3]^2 + 1$ is strictly positive so the sign of `dVdt` is the\n", + "same as the sign of its numerator." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(-8 _[1])x₃² + (-2 _[2])x₂² + (-2 _[1])x₃⁴ + (-2 _[2])x₂²x₃² + (-2 _[3] + 6 _[1])x₁²x₃² + (-2 _[2])x₁²x₂² + (-2 _[3])x₁⁴ + (-2 _[3] + 6 _[1])x₁²x₃⁴ + (-2 _[2])x₁²x₂²x₃² + (-2 _[3])x₁⁴x₃²", + "text/latex": "$$ (-8 {\\_}_{1})x_{3}^{2} + (-2 {\\_}_{2})x_{2}^{2} + (-2 {\\_}_{1})x_{3}^{4} + (-2 {\\_}_{2})x_{2}^{2}x_{3}^{2} + (-2 {\\_}_{3} + 6 {\\_}_{1})x_{1}^{2}x_{3}^{2} + (-2 {\\_}_{2})x_{1}^{2}x_{2}^{2} + (-2 {\\_}_{3})x_{1}^{4} + (-2 {\\_}_{3} + 6 {\\_}_{1})x_{1}^{2}x_{3}^{4} + (-2 {\\_}_{2})x_{1}^{2}x_{2}^{2}x_{3}^{2} + (-2 {\\_}_{3})x_{1}^{4}x_{3}^{2} $$" + }, + "metadata": {}, + "execution_count": 8 + } + ], + "cell_type": "code", + "source": [ + "P = dVdt.num" + ], + "metadata": {}, + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": [ + "Hence, we constrain this numerator to be nonnegative:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "(8 _[1])x₃² + (2 _[2])x₂² + (2 _[1])x₃⁴ + (2 _[2])x₂²x₃² + (-6 _[1] + 2 _[3])x₁²x₃² + (2 _[2])x₁²x₂² + (2 _[3])x₁⁴ + (-6 _[1] + 2 _[3])x₁²x₃⁴ + (2 _[2])x₁²x₂²x₃² + (2 _[3])x₁⁴x₃² is SOS", + "text/latex": "$$ (8 {\\_}_{1})x_{3}^{2} + (2 {\\_}_{2})x_{2}^{2} + (2 {\\_}_{1})x_{3}^{4} + (2 {\\_}_{2})x_{2}^{2}x_{3}^{2} + (-6 {\\_}_{1} + 2 {\\_}_{3})x_{1}^{2}x_{3}^{2} + (2 {\\_}_{2})x_{1}^{2}x_{2}^{2} + (2 {\\_}_{3})x_{1}^{4} + (-6 {\\_}_{1} + 2 {\\_}_{3})x_{1}^{2}x_{3}^{4} + (2 {\\_}_{2})x_{1}^{2}x_{2}^{2}x_{3}^{2} + (2 {\\_}_{3})x_{1}^{4}x_{3}^{2} \\text{ is SOS} $$" + }, + "metadata": {}, + "execution_count": 9 + } + ], + "cell_type": "code", + "source": [ + "@constraint(model, P <= 0)" + ], + "metadata": {}, + "execution_count": 9 + }, + { + "cell_type": "markdown", + "source": [ + "The model is ready to be optimized by the solver:" + ], + "metadata": {} + }, + { + "outputs": [], + "cell_type": "code", + "source": [ + "JuMP.optimize!(model)" + ], + "metadata": {}, + "execution_count": 10 + }, + { + "cell_type": "markdown", + "source": [ + "We verify that the solver has found a feasible solution:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "FEASIBLE_POINT::ResultStatusCode = 1" + }, + "metadata": {}, + "execution_count": 11 + } + ], + "cell_type": "code", + "source": [ + "JuMP.primal_status(model)" + ], + "metadata": {}, + "execution_count": 11 + }, + { + "cell_type": "markdown", + "source": [ + "We can now obtain this feasible solution with:" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "2.9958453255028186x₃² + 12.286107321105156x₂² + 15.718362431619155x₁²", + "text/latex": "$$ 2.9958453255028186x_{3}^{2} + 12.286107321105156x_{2}^{2} + 15.718362431619155x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 12 + } + ], + "cell_type": "code", + "source": [ + "value(V)" + ], + "metadata": {}, + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Systems and Control/lyapunov_function_search.jl b/previews/PR347/generated/Systems and Control/lyapunov_function_search.jl new file mode 100644 index 000000000..325132f91 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/lyapunov_function_search.jl @@ -0,0 +1,32 @@ +using DynamicPolynomials +@polyvar x[1:3] + +f = [-x[1]^3 - x[1] * x[3]^2, + -x[2] - x[1]^2 * x[2], + -x[3] - 3x[3] / (x[3]^2 + 1) + 3x[1]^2 * x[3]] + +using SumOfSquares +using CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +monos = x.^2 + +@variable(model, V, Poly(monos)) + +@constraint(model, V >= sum(x.^2)) + +using LinearAlgebra # Needed for `dot` +dVdt = dot(differentiate(V, x), f) + +P = dVdt.num + +@constraint(model, P <= 0) + +JuMP.optimize!(model) + +JuMP.primal_status(model) + +value(V) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Systems and Control/lyapunov_function_search/index.html b/previews/PR347/generated/Systems and Control/lyapunov_function_search/index.html new file mode 100644 index 000000000..f4f37d65c --- /dev/null +++ b/previews/PR347/generated/Systems and Control/lyapunov_function_search/index.html @@ -0,0 +1,15 @@ + +Lyapunov Function Search · SumOfSquares

Lyapunov Function Search

Adapted from: SOSTOOLS' SOSDEMO2 (See Section 4.2 of SOSTOOLS User's Manual)

using DynamicPolynomials
+@polyvar x[1:3]
(DynamicPolynomials.Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}[x₁, x₂, x₃],)

We define below the vector field $\text{d}x/\text{d}t = f$

f = [-x[1]^3 - x[1] * x[3]^2,
+     -x[2] - x[1]^2 * x[2],
+     -x[3] - 3x[3] / (x[3]^2 + 1) + 3x[1]^2 * x[3]]
3-element Vector{MultivariatePolynomials.RationalPoly{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Int64}, DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, Int64}}}:
+ (-x₁x₃² - x₁³) / (1)
+ (-x₂ - x₁²x₂) / (1)
+ (-4x₃ - x₃³ + 3x₁²x₃ + 3x₁²x₃³) / (1 + x₃²)

We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.

using SumOfSquares
+using CSDP
+solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+model = SOSModel(solver);

We are searching for a Lyapunov function $V(x)$ with monomials $x_1^2$, $x_2^2$ and $x_3^2$. We first define the monomials to be used for the Lyapunov function:

monos = x.^2
3-element Vector{DynamicPolynomials.Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}}}:
+ x₁²
+ x₂²
+ x₃²

We now define the Lyapunov function as a polynomial decision variable with these monomials:

@variable(model, V, Poly(monos))

\[ ({\_}_{1})x_{3}^{2} + ({\_}_{2})x_{2}^{2} + ({\_}_{3})x_{1}^{2} \]

We need to make sure that the Lyapunov function is strictly positive. We can do this with a constraint $V(x) \ge \epsilon (x_1^2 + x_2^2 + x_3^2)$, let's pick $\epsilon = 1$:

@constraint(model, V >= sum(x.^2))

\[ ({\_}_{1} - 1)x_{3}^{2} + ({\_}_{2} - 1)x_{2}^{2} + ({\_}_{3} - 1)x_{1}^{2} \text{ is SOS} \]

We now compute $\text{d}V/\text{d}x \cdot f$.

using LinearAlgebra # Needed for `dot`
+dVdt = dot(differentiate(V, x), f)

\[ \frac{(-8 {\_}_{1})x_{3}^{2} + (-2 {\_}_{2})x_{2}^{2} + (-2 {\_}_{1})x_{3}^{4} + (-2 {\_}_{2})x_{2}^{2}x_{3}^{2} + (-2 {\_}_{3} + 6 {\_}_{1})x_{1}^{2}x_{3}^{2} + (-2 {\_}_{2})x_{1}^{2}x_{2}^{2} + (-2 {\_}_{3})x_{1}^{4} + (-2 {\_}_{3} + 6 {\_}_{1})x_{1}^{2}x_{3}^{4} + (-2 {\_}_{2})x_{1}^{2}x_{2}^{2}x_{3}^{2} + (-2 {\_}_{3})x_{1}^{4}x_{3}^{2}}{1 + x_{3}^{2}} \]

The denominator is $x[3]^2 + 1$ is strictly positive so the sign of dVdt is the same as the sign of its numerator.

P = dVdt.num

\[ (-8 {\_}_{1})x_{3}^{2} + (-2 {\_}_{2})x_{2}^{2} + (-2 {\_}_{1})x_{3}^{4} + (-2 {\_}_{2})x_{2}^{2}x_{3}^{2} + (-2 {\_}_{3} + 6 {\_}_{1})x_{1}^{2}x_{3}^{2} + (-2 {\_}_{2})x_{1}^{2}x_{2}^{2} + (-2 {\_}_{3})x_{1}^{4} + (-2 {\_}_{3} + 6 {\_}_{1})x_{1}^{2}x_{3}^{4} + (-2 {\_}_{2})x_{1}^{2}x_{2}^{2}x_{3}^{2} + (-2 {\_}_{3})x_{1}^{4}x_{3}^{2} \]

Hence, we constrain this numerator to be nonnegative:

@constraint(model, P <= 0)

\[ (8 {\_}_{1})x_{3}^{2} + (2 {\_}_{2})x_{2}^{2} + (2 {\_}_{1})x_{3}^{4} + (2 {\_}_{2})x_{2}^{2}x_{3}^{2} + (-6 {\_}_{1} + 2 {\_}_{3})x_{1}^{2}x_{3}^{2} + (2 {\_}_{2})x_{1}^{2}x_{2}^{2} + (2 {\_}_{3})x_{1}^{4} + (-6 {\_}_{1} + 2 {\_}_{3})x_{1}^{2}x_{3}^{4} + (2 {\_}_{2})x_{1}^{2}x_{2}^{2}x_{3}^{2} + (2 {\_}_{3})x_{1}^{4}x_{3}^{2} \text{ is SOS} \]

The model is ready to be optimized by the solver:

JuMP.optimize!(model)

We verify that the solver has found a feasible solution:

JuMP.primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

We can now obtain this feasible solution with:

value(V)

\[ 2.9958453255028186x_{3}^{2} + 12.286107321105156x_{2}^{2} + 15.718362431619155x_{1}^{2} \]


This page was generated using Literate.jl.

diff --git a/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems.ipynb b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems.ipynb new file mode 100644 index 000000000..c49812bf0 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems.ipynb @@ -0,0 +1,8548 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Stabilization of nonlinear systems" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "**Adapted from**: Examples 1, 2 and 3 of [PPA04]\n", + "\n", + "[PPA04] Prajna, Stephen, Pablo A. Parrilo, and Anders Rantzer.\n", + "*Nonlinear control synthesis by convex optimization*.\n", + "IEEE Transactions on Automatic Control 49.2 (2004): 310-314." + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "phase_plot (generic function with 2 methods)" + }, + "metadata": {}, + "execution_count": 1 + } + ], + "cell_type": "code", + "source": [ + "using DynamicPolynomials\n", + "@polyvar x[1:2]\n", + "\n", + "using SumOfSquares\n", + "using CSDP\n", + "using LinearAlgebra # for ⋅\n", + "using MultivariatePolynomials\n", + "divergence(f) = sum(differentiate.(f, x))\n", + "function controller(f, g, b, α, degs)\n", + " solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n", + " model = SOSModel(solver)\n", + " a = 1\n", + " monos = monomials(x, degs)\n", + " N = length(monos) + 1\n", + " @variable(model, c[1:N] in MOI.NormOneCone(N))\n", + " c_poly = polynomial(c[2:end], monos)\n", + " fagc = f * a + g * c_poly\n", + " @constraint(model, b * divergence(fagc) - α * differentiate(b, x) ⋅ fagc in SOSCone())\n", + " @objective(model, Min, c[1])\n", + " optimize!(model)\n", + " if termination_status(model) != MOI.OPTIMAL\n", + " @warn(\"Termination status $(termination_status(model)): $(raw_status(model))\")\n", + " end\n", + " u = value(c_poly) / value(a)\n", + " return MultivariatePolynomials.map_coefficients(coef -> abs(coef) < 1e-6 ? 0.0 : coef, u)\n", + "end\n", + "\n", + "import DifferentialEquations, Plots\n", + "function phase_plot(f, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5())\n", + " ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f]\n", + " ∇pt(v, p, t) = ∇(v[1], v[2])\n", + " function traj(v0)\n", + " tspan = (0.0, Δt)\n", + " prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan)\n", + " return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8)\n", + " end\n", + " ticks = -5:0.5:5\n", + " X = repeat(ticks, 1, length(ticks))\n", + " Y = X'\n", + " Plots.quiver(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5)\n", + " for x0 in X0\n", + " Plots.plot!(traj(x0), vars=(1, 2), label = nothing)\n", + " end\n", + " Plots.plot!(xlims = (-5, 5), ylims = (-5, 5))\n", + "end" + ], + "metadata": {}, + "execution_count": 1 + }, + { + "cell_type": "markdown", + "source": [ + "## Example 1" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "-0.5738994625385273x₂ - 1.2298305281744644x₁ - 0.12930340072544455x₂³", + "text/latex": "$$ -0.5738994625385273x_{2} - 1.2298305281744644x_{1} - 0.12930340072544455x_{2}^{3} $$" + }, + "metadata": {}, + "execution_count": 2 + } + ], + "cell_type": "code", + "source": [ + "g = [0, 1]\n", + "f = [x[2] - x[1]^3 + x[1]^2, 0]\n", + "b = 3x[1]^2 + 2x[1]*x[2] + 2x[2]^2\n", + "u = controller(f, g, b, 4, 0:3)" + ], + "metadata": {}, + "execution_count": 2 + }, + { + "cell_type": "markdown", + "source": [ + "We find the controller above which gives the following phase plot." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: To maintain consistency with solution indexing, keyword argument vars will be removed in a future version. Please use keyword argument idxs instead.\n", + "│ caller = ip:0x0\n", + "└ @ Core :-1\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=29}", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOydd3gc1bn/z9Sd7U3SqherWZJ7B9sYAwYDNjUQSEgICSGXJL+Um+QmuTeF3JSbkISSQq+hNxvce5ebJNvqvUvb+87u9Dm/P9YRQrKlbRgb7+fx40cazXnn7OzM+Z7znnPeF4EQgjRp0qRJk+ZyBf2sK5AmTZo0adJ8lqSFME2aNGnSXNakhTBNmjRp0lzWpIUwTZo0adJc1qSFME2aNGnSXNakhTBNmjRp0lzW4Bf+kvv379+5c+fYrz//+c/1ev2EcxwOx5NPPjk8PLx69eoHHngAQZALW8c0adKkSXO58BmMCI8ePXrw4EHjv0HRiXUQRfHqq692uVzr1q17/PHHf//731/4SqZJkyZNmsuEz2BECACYP3/+T3/60/P9ddOmTbIsP/fccwiCFBYW3nrrrT/5yU8UCsWFrGGaNGnSpLlM+GzmCM+cOfOjH/3oscceczgck/967NixVatWRd2hS5cuDYVCPT09F7yOadKkSZPmsuAzGBEWFRWtWrUqOzu7trb2d7/7XV1dXWlp6fgT7HZ7fn5+9GcURc1ms81mq6mpmWyqo6PjiWcfIA0WQcZ4AeUEYu78K+bMXapQmbI0ZhOJabD4lL634e8c4yLVWUp1jkqbr9QXUarssb/yrI8JjegzZ8dobaj9Lc9IrTlvmdZYrjXX4KQmllIQyj57nSln6YTjPtsJR/9uY/YCc/5V5zMliQzt69Znzpn2KnzE2df0fF75nVrzzPHHg552tb4Yw5WxVHU8nSf/PGPug4TCCAAIB/oVygyc1MZrZIyBllcLZ34RxRVBd5su4xxf/dS4hg4YLPMJxdm559Hujywla5jAoNZclXCVmNAIAFCpLfBYj6oNMwTWrzXNnL7Y+Qm4mrSmKp5xc2ErSqiTtMYEh1BcKYnmlqOtNctUSl0hihIJW+NZr8gHVbpiW9+2zPyVAh9SanITtgahFHS36DPn2vq25cy4KeRpT+aLAAAEXE36zNnuoUOG7IVMaDhJa5LIsGE7BADyEYDhGmMZgmDJGAx52tX6EufQwewZNwRcjfrMuQmb4hk3hFChMlu7P8wtv2PsuMD5uYhbYyyL3VTA1aLPnAUAkGV+uPW1otnfiL86MOBqntC8CFygr/HZ8kX/iaLTq4nfccpgWTDFCXSgd7Tzg7zKOzX6T4gCF3GJAq3Wl8RaUQAcPrGjp693hC7ONdx67TRN4mcghPfdd1/0h+9///tf/OIX//rXvz711FPjT6AoShCEsV85jlOpVOc0FQwG93UaVt93Bw3lMEBogI4qNO90OAOyNwSHgkDJA1wHGC1gtYDRAlYH2OjPBlw24GgGRZiVKrNCadHoM7VmjcZSufhBv6slEhhlwzanp4Vj3CIXhBACcDYiK8d4RYHWGspU+nxKZaG02WptgdpQrNYXTa5e2ex7oeB39G0J6Qr5xudkWQBQBgAgKIYguEpfqDEUa02Vppx5JGUaXzCESr0Nf65Y9F2F0vzxbSlZjgLRYz1h69koCQxAUARBVPpCU+6SrMKrVJocAAAAqoDt0FDL8YpF35m6HVSpinMKVwy2PMfRTgCA1lxZNOseY9ZcHJ3Rfvyv5QsfVmnzpig+GV3GvKa934dQKp71lZzSNa21f5i98lcJCGqUjJxZJ7feUzbvwYC7IyOnBifO/QCcj8y8uaNdH/Ksz5Sz0FJ0jdFYWLf53ryKdWZLZYzdkclQVEl/0788w4ylaHXzwZ+Z85Za8qd6pacFMRd11f+lbMFDLQcfyyxYkaQ1BVnSfvzPeWX3DrZnZ2TurL5yJoolLoRKpaL92BtZRattne+o1QacUKpUcbS5k3H19/kFX9B+XKXUBj2dloKFyVgT1PqRtpcxQmPveluS+SStAaDsO/W4OW+J394EgWzJ/1Vy1sBg0/6Qq4HjwgHbIYEPqVRXJGzK3rMvt/TGU7u+VVB1d7QZ9NoabP27SYWusOouxXkaxsk4hw4CiVWpVEPt7/c2vlix6Dvna1SnoOPkE9nF1/67oNxz+mVr72YUIUpmf0Wj0U1bvL/5dUKhnXzdgKtloO2doKsNQlmhysgtX5+VUzPeW+keqbUPHJi59IdTtwM9PR1t3f39DtHFFHiEYgqlLRpYkq2fVzVj2rohn23Q7f/7v/87duzYpk2bxh/8zW9+09ra+u677wIAQqGQ0Wjs7e0tKjqH0jQ0NDz00EMNDQ1TXIKRZB8v+XjRJ0g2RrCygo8XXXTAwzAenvPzkl+Afgn1QxIFUAsZLWC1CKv59w9awGoRTiNHtIDR49BEKowkQnqaUQwWVd3JRDws7eAiTp4LRC8HoTx2aZzUKpRmSmkM+fqUasvsVb/G8LNfpMhHwr4ev7fb72xmgkMc65clHsVIAACEIqXMUKiy2YhTby6vvvInU3iwA44mx/DhgLsjEhqNXl9BGdX6ItrfN+eqX6sN0z8BUVwjR4faN9L+XklktYYSSWQrl3zfaJl+ZDlGKBTSarUiH+mq/7tr9ASKEpTasuj6x5AY+onhwOBQ+/sAQVWaXEpjUWpylJocQqE5s+9//K7WzPxlNcv/O/aajMfnaLL17YJQIhT6obZ3q5b9MK98fWKmotD+/t7Gl0OeboLULF33fDKmAACiEG6t/WPA2ao1l82/9tEkrUEotR37c3vDLAXlX//N+5K0BgDoOfU8x3i99oa5q/5Xl5HUgBUAMNy5kYt4R7s2Fc26t7jmniStuUaOBlytI11b8spuLF/4H0la8zubrb07/M623LIbkq9b27G/uIZrC6ofgJK3dO7XkjHVevRPHO2kNFmVS34w2r0l4G4zWubllq2Na7gviUzbsb+UzPnqmX0/U+uL51/z+wQmxTpP/s2ctzQjb6nHWtfd8DQdHM7MX16z/L9wfHpBlSWh7dijuWU3mbLnR48EXC0Dbe8HPe2yJBCEKq/y9oLKWyePKaEs9px+gdJYCipvn/CnCG3r627o6HdYfZSbL3Fz5SgCc/X+8iJDeVFGaQ6iVSIAAFmWJUkiiGlu12cghG63OyMjAwAQiURWrVq1bt26X//61wCADRs2LF++3GKxtLS0rFy5sqOjw2KxPPfcc88//3xdXd05TcUihLETECQvL/p4ycOLPl7y8qKXl3zj/vdwnI8TvbwoQqhDuFytoVCtzKaIfBWRQxF5SjJXSeQqCQtFRHd7sBF3ODjos52x9e3hOe+C6x43ZlVPWw1ZZAOeTsfAAcfgfiZkW7r+5VhKjRF0t/Y2veEeroUQXv+1Q/HeBIEL9jf9a7hrMxMcufGhegyLdUjndY8SaISNuNmwnYu4A642x8D+rKKVi274e4wWZElgww6GtjG0jaUdHOtFUZwJ2Ua6N119zxadqSLezzLesr1/T3/Lm2F///VfO5KwnSgQyn0tr7Uc+u2t30nB1DWEcsuR3w93fHDTN88kbw0AcHzbyx0Ni+//n1lIKhYADLa9e2b/L9c+cEShykzemrV3x6k9P1645q85M25I3tpoz7Yze/978dons4pWJW+t+dAjI93brr//YMJujDEGWt/urHsyf+aXa5Z9Nxk7EMq1G7+MEUqTZZ7A04VVd+rMlQnYaT36FzY8Gg6OLFrzhEo35umBHOPjWZ9GXzRtb7Wv8VUMVzpHjtC+Po1hRs2Kn//bBTU9POtvO/bnioUPC4x3oGOD39kEAFBQxpyym4qqbp9CkpmQtbP+qbL5X9cYZohixDl4eKCvud8petgCN1/i5koxDC/MFCuKTEUWbEY2olOdY5fdxSuEs2fPpijKbDafOXNmzpw5GzduVKvVAACNRrNx48Y1a9YAAL7//e9v3Lhx9uzZdXV177333qpV537QUyuEUwOhbO/f47HW6cyVGWXrAxLqZMURhrcxwigjWBneygqjjGBjBC8vZimIfBVhhEETb8siwayihQU6XVQpDcRU0w+SyNr6dvudTaTSVFR993jX6NRIIuexnvDaTgk8nZG3xFK0OnbPGEvb3da6sL9fkngExcw5C825SzCciqVs96nneNaHIBhEKJ0xj1JnU6oMhSqLpCbuDf2cwdBOpSYrVdY81npz7qKUmKJpesfL9qVrCwvKyZQYbDv+WNXS7yFIaqZROur+lpF7RUbe4pRYO7n1W7NW/lqlS3z+cgyO8Z7Y8uBVd21I3pStZ0dHw1OLb35To0nQD3/WTu+uht0/mn3VL/MrbsXwBJfND7S80Xjg19kl12pNZQAAZFz/iKQMpNKUW3rj1C/7ia3f8lhPak0V1ct/Ys6O7ym19exoOvK/CsoMUFRrrCiuucucuySWgh0nn7D37RUxs5srdLIVHrHMK5TLQJGfSZTnYWV5aIkF0aun319+8QohwzBNTU00TRcWFpaXl48dHxgYsFgsSuXZ7lh7e7vVap0/f77JZDqPpQskhAIXHO7YGA4M5pbdaM6d/gUOhRyN7dsHaFo0LwipSm2sOMoIVkawMvwoIwgyzFMSOUoiX0lmU0SBisym8Dwlrgx2EK5aXObyy9frM2NdHsKzAefQoaCnE0LJUrTanLsIiXkgwEXcPWdeRBBUY5hhzl10zmnO2Im6RpOxkCYl0DRt68H7W9nrv2z4rOty+QIhDIfDSQphSpAkBkA0YR0FADiHa2WRiYSsXMQNoQQgBAgKAFCozCptntZUpjn/FMxI52aPrR4nVQiCagwl5pxFakPxFNdiODDilgccsK7+oIcvicjmPBOckacqtqBFFjTPHHdklYtXCFPIpy2EtL9/sO1dHFcW1XyRUlumPd/vbB7p2kSpsgqq7lQoz63fEUkeifB2VhyO8HZWGGH4XufAaIT3IHq7gFooolSjKNUoyjSKUo2iVK0o1Sh05xlE8qxvoPXtnJLrtKbyc55wIUkL4UUCTdNKSv3OE56bHzDqzUmtfkyTMBePEH56cBFXJGSFUDJlx7TOK+p5ov19siSM9zwFwrBtSG4bkjuHZYYHxRakyIKWWJBiC6olA86hw0FPhyRy8Tq6oqSFMAVEgsOU2hJdwxILPOsjKQMAiQeE8/FSa5BpC7J9NNcX5vporpvmMATMUCtmaBT//p+coVGUqBUXVdy5tBBeJNA0rdFo6vfSogCWrf08N8QXM5eDECZDKBRqaO3rtlFDwWJ/GMwsQKsL0apCNNt47lZNlgXP6An36AlZErSm8vyKW2JUxBiF8LOJLHOpoNIVxHU+SRmTvKKRxFZkaFZkfOL9sbNCD8310lwPzR1whl6kuV6aEyAcGzKWahQztdQsvdJIpkcAaQAAoHqxasPT3oWr1cTF1V9Kc/kiy2DIJbcNyW2Dco+VyDVXVReiyxeilfnotPu9UZTILFiRWbACABDy9kAoAZD47qDJpIXwEiCbIrIpYoI6+gWpJ8T1hrlemjvuCb/c724Nsjocq9FTc/TKGr1ytl5ZpaOUcYYUSPP5QKVDc0uI7ka2ekmyayDTpEkGVwC2DcpR52emHqkuRK9bgH/3FpRKdC1XdNVPakkL4aWKgcAWmVSLTJ/YxGNlhLYg0xpkj7rp5/vcp3wRA4EtNKlqdMpqHVWjV87SKxXo5TREgEAIi4Qmlc+5o86XOd+A4im7jfQIIwtQVxL3Bufz4ajzWRYba5apDn0UrFqsTDJ3S7AvrMxSpPAe+rtoQ0UqfYYRB6eyXESxiPmAQOgu66Y1EIZdo3LbkNzUJ+MYqC5CF1WgX70OV1MXaeNzWX9bnz+iGxmvs5yN8iBC2BXiWgJMc4D5cNT/2zablREqddRsvXKxSbXYqJ5nVF1suiiLMIUaAwAYPeApXjf9QqfYwSksYmc1+akbaUEgMlLKrAHAeQUAgKWQUCjR4S6usDIpkWDcvMKYmp0YUYL9kRQKoRiR/F10YkIoCzJKnMNlIoswPMpoixLsmtiP+wquT8G2y/HQI0wqH7lPAUkGHcNyQ7fUNiSzPKguRKuL0HVLcbP24mphzklaCD/P4AhSraOqddTdBWcnLyOS3BZgGwORem/k5X5PR5Ct1lOLjerFJvVik6pKR2EJDR+gnLIlV856vyaX0hSm6J1HgMJIsB6eMqesKVfnUYGecApbJRRHZOFTWbM2a5my5RiTpBBCESKp65qkvKOTzHBwcJuj5NZzbAx3nfZrC1I2QE8BEHiaghenEIoSaB2U67ulxl7ZYkQWlqPXzCPzMi6xFLJpIby8UGFo1KH6jRIAABBk2NgbaECF/c7QXzrtI4wwW69caFRF/1XrlTE+zcG+iHcgpL0uBatGs5cZ+zfZFSYiVb44y2LDyAF34fUp2/xOGUmnz58qawAAlEBlUZ7+vPgprqbqdoc9NtGck/jNlCWIYilr1iRWwhSJLOnyd9JKi0JhmLhEgnFyCY8vTTU6b2vIVDPxuWWcvGVxsgvfUoi3PWSoTNkY2lbrNc/Wkck5bwURtA7J9V1SY5+ca0LmlqLrl5JZhktL/j4mvZJiKlgv72rwg5g76xInWw97ZDG+3j2U4dAup0CLcdcPAJGR+j60sV4+gbIAAAJFqnXK6xrFF2bmta6tGVo3+5GanGyK+HDUf8Oh7vzNTfce73+qx9UaYKb+SPoyNWUhhnY4Y79XU1B4Q9bwbleqRpkoiSIoIoZT53tEQGJ7jiROth/3Tb5FKJHgiNB+1BvoDU9xAoqCmmXKptpILNYCvWFnwzkEHkoQiV8IRVbq/8gmcRMFXuJlTJFIs6MvU48ecPPBia8J5xMmq2PsNgM9YSh94ub7O2lDuToxg1MgspLtiDexsoHesH5Gaqrk7w6jJJKwCvIiONMnv7BD+P4/me0nxaIs9LdfJX9+D3nTYvzSVUGQFsKpoUykMkvRu9HmbgzEcj6mQM2zdcO7nM76OOQTQZHclWbHCZ/tqDfe1h9XYiXrs72todGD7sSUQ2VRlNyS7Tjh87aF9AR2nUX386rsDctLR9bPqbuu6o48Q6M/cvexPsPGM2sOdv+pw37ETQvnupCmmMqYqxvY6pjQrCQApkBzVphH97uTtDNG9lKjo96XQMFAT1iMnENBE3vjMQWqyaN6N9r4gDD+OIKjMKERYfaVJj4gWA97pnjYZi5U2vr5oHf6foC+VK3QE4PbJ36DiTkzcQorWJM1uM0xoZcmsTJGJdLsIBhSfLNlaJeTD03qMibRAmdfYXSc+MSz4euiDeUp3v/HevmBzY6M+YnEHeT8AmUik/mMH5vyCYEeOoHB7pj+/fBZdvtJUesO/3Id8vN7yDULMIMm7poF+yOjBxN5u6EEQwMx9eriJS2E06ApUJbekYMrsf5NdnqEmfZ8hYEousmizFT0fWQL9sf6neFKLP/aTEOZemCrI/ZSURAMyV1pNlZoej+w0aNsXGWjoDhScH0WlODQTuf4RjBXSdxVYHx2UVHr2pqOG2u+UWIeivD/UT+U+VHjzYd7/tzpaPR/YqSoyqGyrzT2fXiOcUC8KDNJVTblbgomaScKocUFWop3pA4AUOVQjpO+wR1O4ZONL2kgOJ9wvlJToClQlqy32I/7XKc/7lolM0eYucCgK1H1fWQT2XNLHU4iFQuUrcdjeqj0ZersK0x9G23jPx2UIJLQiipchZXcmu2s8wd6Ph62SlyCI0IAAEqgM27JHtnj+sT4PjmFUGYpOL8w1t1hnJw6m0qJ6owRGozYj/lK78gh1In4hJ31/swFKYjcK4twZL+7YE0ccwSSDE71SH/7kP/hM+yhJrGqEP3j/eQ9Su+ta1U5pTHFIp6M44QvNBTJW5URb8GIg+v7yIYndA+nBXvkkUc+DbsXBpvNNnLCtax6Oe8X+KAoC7IkyCiBJPbeAgB8naHQICMykizICAAoefaNpcyksUITHGCcdT4qg8RV03wZCgNhrNQ6GwLW/S5MgRIa7JyL0yZAqHFjpSZsY+3HfCqLAqc+cRXWwwf7IgiB4MpzXJ3Q4qZqra8j5GujtUWqae+AzMu+TlqhJ8a8XiqLgjKTQzudykzF5A+oxbFZeuXNOfpvl2U+OCMjU4E3+pk/dtj/0G5vDjCMJJPDrCVbg6swXZFqaIdTU6DEyMS7WaEhxlCu9jQHCTUe12Qh4+RQDJ0wggnbWE2u0tcZ0uTFt9wAI1FdsUqdQznr/L5OWm1RYAqU9fAojnA+QZmVyBoNBEP0ZWohKNqP+7RFKlmEEiPRI6y+NEHfF6kjtAWqoZ1OhYEgtHhwlBY8sr7sY2vGLLx2C10xn8LJ6d8LnMIMFZrRA26AIJSZjDjYiJ0bby0uEATRl6kDveGIjVPnUhEHK9ASTqEJOzMRDNGVqAe2OnQlKt4vogRKjzC65NyG6hzKfsynzlaIjOw47stZYU64AYkS6A3rS9QhW1hlVLobg+FRtvCGrMRsQhn6u8OmKm3ExhLapGb1Brc781aZCRUGAAgNMQr9VF+BzQu310kv7RScfnhFFXb/GnJFDZargaPbHQXXZSqMnygb6A5TxunHrBInD25z6EvVGfPOr+sy8HWFCQpFx7ceEDhO+sJWtmhtVlytgczLgd6wxEsK3TRr5S75EGv/+s07P3r4x5IgiYwERSiyMpShGJFxJSqyMk6d/V/iZJRE5ej/EkRQAKSzfUmURFACxQgEU2KcVxBZWZZlBACZlwEEAEUwAoEygmAAwRFEhmxQkgVJYSIxHEVJBKdwQoPiFIYpMVyFKQwEocFwNU5q8EBf2NscCvSFpYhEaomPh9/o2US/mBIlNQShx0kdThkIhYlQZVIABRIv22u9UIZ5V2eMCVXExTuOeViPINBi9CCUIIohpIFUZhDqbIWqQEkZSdbLWw95Mufrp178LbLy8A5H2MpCAKAEMQrV5qv0lWpdocpa6yF1RGZsbpyBML/THtjlCO4ZDeTz6BU8ca1efdMSi6fen7cqY8ILEzsj+1zuM0HjTK3ESkU3WWJ3ptGjbKCbFlkZAECZCG2RSpWlcJz02497tYWqGbdlJ9zZF8OS46RP4mR1HmU94jVWqPOvTWqJvECLw3tchjL1yH63oUJTeENyy3kgsNV6CS02tMuZMUc/wdrRrSGFEl14TRyC4TjhE1nJ0xTUzVAV35ydVN0A8HfS/m6a9QmqLEXGXL0qO6mFrCIrDW5z4iocCpKmSJUxZ/qssFMzesCNyIClRYUWz1sd92BlAiP7XFCCHCeodBSpw6dq96fD3Rik9MTgLoe+TJ1/zdnnjXHxgW4aoEj2slidnPbjPmUmqS9VD+92eZqDhpnq4pvO8Z0KIjjTJx1skqxeeGUVdtVsbGzmTwiJgzucxTdZomMyMSLajnj9XWEoQ3U+VXpb7tTuRcbJWY94CtdkTZBzWZT9XWFfWyji5CAECARKi6LwhqyxWUzOJ4zsd1uWGKZeNBvVvOAgE7GxY5uREAxRmgnzYr2haBpf9yUvhMnHGhVpURRkISTJgizQoixBMSTJkiyEZQDlqE9MiEhQBjIvoyQq87IUkXhaXPqbKjbACyFJoEUxIvFBQYxIIivLnCREJImVERxBIJAhECMi5xOX/KoC++Qgj/eLjJfj3AIXEPiQIIZEnpYAclYmRUbivMLiRyqw8wdOk0WZsXP0MBNxCqyXO6uRELAejjIpZn+3JPab4O2gA3006xKgDMWIBAGy8KdxRHDwBYNtPLrTHtza5+tl+Cs4fIUHvXdV7owFcUxISJwcnemUeVkWoeOkz90YRBCw4KeJRBVnvXxoIMI4eQCAyErOBn/htZm5VyfVzIlhyX7c622jZUme94PSZExFcZzwWY94lFnUzK/kJ2/N2xYa3OUgVUTNQ5/IJRIOSB8+67vre2Yynh3NwYGI9ZAnYmMTu/8TYFz86AGXvzs8++GShHtIY4iMNLjV4e+hqx4oSn43vSzCztdHhJBQ9bXCJAdeAAD7Ma/1iFdTSuYuykxyI1D/h/bgQDjnKrOxQhPoDYdtHBRkKoM0ztTGfg9DgxF6mOVDoq89ZKzSFt2QNVm0BhzywWaprlMqtqCr5mALyrDxMak4nzB60F18kyVs5Wy1bsYtICgw1WhzV5jRGBw/nuYg4+TyVmcgKCKLsr8j7G0PRewslAGCAlU2ZarSmqq1k2vlbgzSw0zh9ZnjryLzcmiYCQ1GIjZWiEiyAGUBIiigTIQqhzJWadU5H7tt07FGYwXX4DgAMUUJhcDbFgr00PoyjalaCxBAGacJLxrsj3iaggoTkb3UOPmJIQ04acDBpBwmwf6Ity1EaLCsRcYpVBAAgOKoOl+p/ndfSWQkd2OQdfOZCw0xDumi4Bo8a5FBW6T0toXEsISrMN2M+F5gVIRzIlhpiPoGkeHF5QMqdr+Je7R/YLbfeVeB8Y48Q4HqvN6JYH/E10ljJAIAQBBkbPynzqXUuRQ9wgIJgPinBigTSZnOXlQWZMNMTcTKxW3lk+BqLP/azOxlpt6P7EmaimJZatQUKFO1MshUrQVqaWTTxJVBaj1WUEG210XmroxjUKgrVlEmsukffSmpmzKTLL45u/5P3SnJbIgrscK1Wc4/BJQZKdghiuKIOk/hOZ2s+zGKQEtSRM5YqovXFT+BQF/YXufLnKNn7JwUkfTlmoy5cQ8uOQ/f874VwZCcpcZ5/zmx60Yz8GibdLhFkmSwchb2+68pJif5o0eZoe1OKIHmpwdIPZ5/TaY2ZnWHMhza44QCECNSy1MDsgQBAOpcylSlLbtzqkGkQIsje136co2xSmM94gkNMmMLhqPaqStVZSzQU4bU7A9OjwhjQuJkZ50v4uSyFhljeQhkEbobA/QwYyg/K5mxILKS+0wwYmd1JSrzbF3skwpQhoGecKA3jKBI1iJDXJvHoQxDg4y/m5Z5SJkJ0ywdGU9bYD/q5YIiAECUeWOxXpNHkePmHsKivNMe3GT1b7UFitXkXfnGuwtMxepUhilJM4Fo9onJx/1uadvLvru+Z/5cheFOqId0PlN8kCdTEUOHtjE4hYqEkGT2CW9bCMrAVK1JZqi6pHgAACAASURBVM5yaK+bdbKklsAoFEpQFiGuRCVW9orYcZ+ixY8vqMSvmo2V551XlM480YMpMG2hSpWtUOdQKosi9u007S8PhgYY3QxV9pXm2DelSLxU90gnaSAUelKdq9AUKg2lajyhjcXpNEypQaBFZ51fiEiWJUZl5vQviRASHSd9Ai1ZlhpjnwihRxhvSwhBQdZiY1xeo4id87YGhYhkrNQYyjVxTYCJjDS6341giK5EpS9VJ7BXDIwLUjV1GiYJwsMu+t1h3wcjvhKN4osFxrsKjPnKtCKmnvMJIQDgwAdBowWfu+JiipnyOeViTsPUPSrvOS11jcrLq7Hr5se8/wECxs2HrSzjYKEMAAAYhapzKU2hcsKyvskF6VEm0B0WwhKCI8ZKja5YNX1LBUFwIOLvoqNheI0zNQk2UGkhTB5vW4hxcpalxnMu1JyMrz0UcXKWxcZpl5WOx3U6gKCIeZY23m9aZCV/V9hUrU1tzKrEiDEfoQThPmfonSHfR1b/TC11T6HpnkKjmUy76FPGFELod4nbXvF/3gaFFyUXoRBG90LsbJBoBl47D181B0vytRNZKWJlMQpT58a6lUJkpUBXmB5lAARUJmmq1k2/peRjRZR1Jep4FTEthGkuKPEm5hVkuNsRfHPIu9UaWJ2lvb/YfFOOnrjIIoBfikwhhACAAx8ETRZ8TnpQ+ClzUQkhw4MjLdKuBtGkRW5cgs+dcVG8ZoyLhxKM3W0GZRjojQR6aEyBji2gnZb0Ypk0FzUEityUo78pRx8UpPdHfI91OR6qH7yn0HR/sXmBMd1Mf1rMv1q99WVf1WJlelB4ORBm4c4G6UCjNGcG+r3byILMi+hLj2WmaTwIihjK1Z9G9DuQFsI0nzk6Avt6ScbXSzL6w9xrg94vHO0zkdhDpZn3Fhq1+KcSReKiws8FKIyi8JSl0/Oy/ikGInozlldKthyPzF8VU4MiypIMJRJL2WyuDGUUSQe0+tRhebCvUdxZL80uQX/xpUs4HPaFIf1EprlYKFErflWd03PTrN/PzttlDxZtaX6ofrDOO1VQ6QvPq83vpNbggH+ow9OVQoPbB/ZOfcKCq9VtJxiOiSkMXn9gsM52JhX1Osvrre+l0BoAYHvfXk5KMOj8p8eBodrP6tKcALbViT99kbN64P/cSz64lkir4LSkhTDNxQWKgBuyde9fOaNtbc0MjeKeY/1L93S8Nujh4g8pfnj4WKu7I7XVw1AsLKQy7G+2xmILO1NokMIVrDjVdkmtESuuVjQdielTUJiCEacPsRs7kpzihFM22q5IdMC6tXe3fJ5FElt6diZRKdDvH0qm+Dmx0tNsXY1K4E9e4AYd8L/vSUtgHKSFMM1FxK7+/QHubKDtbIr42czs7ptm/bI65/VBb/GW5l+2WEeZOEJdryhYtmfgoCAlEh37fCzLXXjcmsrFWVmqDHfEk0KDKlw5rVTPX6XuPM2Gg9NrkpJQMmIikdwvIIm39cX6gkPDRycfP2k9laVOcYr5JOEl/sOubef7qwzBgSbpZy9xo2743/eQD68jLMa0BMZBWggvbSSYVJo9QRKGg6NJ1iHE0680vyXIieRTnMBVBVe+1PSml/k4MAqKgHW5+p1XlR9YXeHnpTk7275yov+MP6bRDAKQL1bdvqFra/IVG6PMWNLn60+hQRRBRTl1uRIBUBGqsDCNP1mlRSsXUGcOTu92VuHKiJDKEWHCvNbyboinU2uzJmNmi6t98qCwwd64JGdBaq+VJB92bbulfO05/9Q2JD/yOneyU/rhHcQ3bySyp5PAsBD5qHv7p1DHS5i0EE5Fo7N1Qrs8Nf3+wRcaX3dF4guXNRKyPnP6lWn9HuekxdXxzOlXEh5SYCh+0nbq7faNybTFWlJzU+maF1vfSOwjjIfCFQ/Pf+DVlncm3/NKLfX3BQW9N8+arVeuP9x73cGu7bbAtN7SbHUWhmD9gVT6qQiMSGxSaig4ksJqDAdHN3XvmNyIq3ElzU+vcHNXqAc7OJ/zbPdFhvC1lncnax6FU2xCI8Jd/fsPDx9PoOD5+MLMW15tftvPxZQZNHZWF62YMCg8aT21MGduaq8yRmIvmo8NcBKfr82dcNzug09vEV7fK6xfiv/XXWRh5vTtOStyz595bXXRigSqMZ4tPTudcTZ04+EvsmndtBBOxdysmnur79g/VPtS0xs+dvo3sMRQdF/NXfuHap85/Uos50fJ1+Z+Y+59dbbTz5x+Jd73fG5Wzddm37t74OAbre8n4ANEEeTOyvVXFVzx9OmX2pNYspGlyvjmrPv2DR45PHwsYSNRptBCAICBwP5rZnbfzbPuLzb/vHl0/q62t4e80pR7Ye+ovPnDrm0yTNnU1JKcBfUJrR/xMr6/1T/f40tN6M4CXd6szKp/NLww9MkxvYZUxzKLSVLInBWq+r1nJRNFkPXlN7zc/NYpe9P401AEOd8s2tRcX7IaRdB/Nrw49YRl7Chx6sG5973a/Lab+TjPe4inNWRS6+knDwqTHw6GhYiKmBiIMcAFnz39altCk9bvd3x0R+W68UdoFr6+V/jjO3xZLvrb+xWLK2JaXy3I4rNnXv3qrLt1ZBxbficgQemV5rfytLlZqgTj1+8bPPxB55YECtrDzn2DhxO76DTAS5n6+voFCxZcgAv52cCrzW+/3PQmzYdjOT/ABV9tfvulxjfDfCT2qwS44But77/b/hEv8vHWcDRke+70q0dH6uItGEWG8tae3S+ceZ0RmMQsBINBCOGhoWMvNr4hSGJiRsZgBPaxk097It4pzpEh3Gr1r9jbUba1+bleFyfJ5zuzx9f/Udf2eOswGrK92vx2t7d30nXl5878K15rUSRZ3tm3/+lTL4//aK81v8tLQmIGRVl8v2PTu+0fSbIUPdJq7dg/eCSmsoL8zhNuW/8nHrb9g0eeO/1qZNxj8FLjm4nVDULoDLv+euKpHl9/SqxBCHmRf6rhJWfYFf21y9t7aOhoMgYhhC2u9rE7dmK04YS1IUmDoyHb9p49oVBo7Mj+wSP/bHgxwAUTsNbt7dvcvXPsVxnCI63iD55h39jH08x5n/nJSLL0j4YXbbQjgTqMEeCCT9Y9Zw3ZEyse5iMvnHn92GjczVS0gfpX8zucyMVVUJIknp++Ob30hXDJohQa5KSp7rIz7HruzL/ebtsY45cxGrK90vTWlp5dohyHMAwFRv7Z8OLOvn0y/MRTLkjStGXrbWeeqHt2MDAcy4UmG3RHvP9oeLHB1hh7bcfwB/3RH4YCI0/UPeOeUsOmRYJSLFoY5ZAztPZgV+Hmpqd6nOx55PCVprcSeHs5kasdOfFi4xuvNL09/q6+cOb1hKULQsgIzJutH7ze8l70QdrZt280ZEvYGoSwzzfwZN1z0RoOOAc3d++ItWALu/Fpj/zJe+ZlfH+vf/6MoyX6a5LSJcnypu4dGzu3psQahJCXhL/XPx+9Y4eGjnZN6qkkwN/rn5dkGUL4VMNLyVtrc3fWDp+MCqE1ZH/85DOn7E0JW/tb/XNjDYjDJ//5Pe7X/+L6bNO3BuORofzc6VfHnmEJxlc8ylBg5O/1z08eDMRord3d9UTdM9O+0ZOtjYZsT9Y91+Hujr2qH1uTpAjLTnvaJR9i7Xsf/Wz5NStYgREkSU2oEASh+TCO4kqS4gSel3gVQWEYHmJpFEPVhEoQeVbkKZwicDzM0QAAtUIjiCIrsgqcsEfcIS4sSQKJkxKQUIihCEAQFEFRSRIpXCFCCcqAkxgFRpUaS8J8WEOqIxJDIiSB4zjA1KQKAKAndQiKDodGhwIjoiyFhYiGUOZqcgVZIFACAFmQpbEfVKSSwkgFpjBQBgqn1LjSpDLYI64eT98NJdcuz18c/bCn7E3n28SmUaiNCp1JaTApzRmUqcPbLcrSV2fdPdk/M4Yn4v3d0cdFWUQQBAEIBJKB0udp8kr0BT42EBLoe6vvUBNxRHj58d5f8zIHADBQ+tmZVVbavjxv2aKcebFbGM9jJ5/q8Q3k6/IgkB6e94BJOX2WrJPe8COt1tPe0MMz1A+WmDOUurFt4K81v3vC3lCgzfvpsu8lVp+wEDkyfHwgMKwmVCqC2jNw+OtzvpTwp4vijLg/6t6uIzV7Bg/9x7yvLcxOal5KgtLGzm0QwB09e9aUrr6n6vYYC2592VcxX1k+b2K4yINDRzs83U3OtrmWWQ/N+0oydQMAtLm7DgwdGQmNmpWZP1ryH0lak6H8YuPrQT7MScz/W/iQlkw2klmru2Nn3wFRFq4uWp78Mpnj1vp66xkUYLk6S5AP3Vt1B4ElmH/x8PAxHMU3d+/M1eTPgPdtr5NuXIytXYTHGyTt1ea3r8hbPMNQ9FbrhuPWuhxN9i+W/yguCyetp1rcHV+bfS+KIAAAV8Szo3fvGWezIAs4ij+6+n9x9LwTbTKEW3t3yVC+pXwt8slVvhGRPWU73ehq6/cP8xKLAAxB4PcXP1yiLwAASFDa0rPLzwa/VHMngU4V/sXL+tvd3X2B/uHAqCviHWvZZCDdUb5udfE0c6KXvBB+erFGeZn3RM5OU/m4ACdxAABZlk/YGgb8Q5Wmym/MvXf8+TRPh/iwDGUn4wYA+BmfAKWIwFpDtk5PjwInH139yDkvxIq8j/V5GS8tMAE+EGSDEYF1RFwdnh4Cw5654a/TVtUV8Vhpu4N2uhmvh/UOBUf7fANzs2p+teInsX/e4dBoj7e3PzDU5e3r9Q0aFNrnb3oi9uJjsUaHQ6N7+w/Xjp4YDdl+ceUPr8xfGruRMSICM0rb9g/WHhyq5ST+/dtfiqWUDOFbfc3/6OP6wvC2TN9irWfs1aT58O7+A+vLb3ho3lcTqM8Yfi5wcOjo/sHDPjbw6rp/JmMqyhlny6PH/z4nq/pny76fvLX+wNDvax/XKtSPX/u7GIu4RoW97wTu/K6ZICc2ro6w8+/1L3T7+t657YXk6xbkQ8+d/tfhkWMf3fl68tZkKP/j1Av7Bo98eMe/krcGAPjPvb8SJO7v1/8peVPb+na/1vzeEsv826puLtEXJmxHkMVfH/6TPWy/Lf/ho/UlRj03d3ZvSB4NC2EIgZKgYuzuvN7yHopiLc42WqCvzFv6hZm3TiFa52RT9w4Kp4oNhbv7D3R6ugRJonBqae6CdWVrNNP1Qhxh15ttH9xSvrbUUOygXY3ulm5vf79/KLqmQQRiia5gjqVmSfZCA6UbX7DPP7ilZ9ct5WuL9QXRIxGRHQlZBwKD3d7+weAwJ/AAAF7iSYykcEWmypSvzavMKKvJqCTRfyciTQfdTi0yhMetdafsTQuy51yZtySWIs2utoNDR3M02evLro89SFWnt+foSJ2KUN5cuiauhQCCJNSOnuz09JQYCq8pugpH44tPNjboyVCZry1eaVDElwI0FAqFkPDx0QZXxE1g+OKc+TUZVdHO47S4Iu5Wd+doyMZLAgAAAqgilPna3Hxtbp4mO4HedK2b/p9mq4MVfjs79878T2VHFS8JZKLd/AmIULKHHPm6iWsCEyMYCrYFu5blLYq9yMGNQbUOXXTtOVo0COB77Zvurro1JXUDAPyt/rnvLXooJaZkCH9b+5dfx9Pbm4KPurbTQujLNXcnb+pPx55U4Iqvz/yyLp4w9JN59PjfGmxtFdK3nfbC2bM75pUi2eqsHI0lLlfNLw7+ocnVNitz5pdq7iozFFF4rJkixrh300MkqtCRmgJtzqqiK5fmxvFoPVH/7Clbo16hxVBMhkCr0Mw0l83Lml2TWYmef6kmzTN/PP54RGAonKL5EAAAARgAAEORXE12ob5ghqFopqlsWg0GaSFMIaIs7R042OHtvq54VU3GzGnPhwAeG62rs52ZaSpbU3J1jJEVo0Lb7GwvMRReW3wVhsQhY+6IZ+/g4SAfuqZoZamhOPaC0euedjSdcjSRKHlN0YoCXV5cxYN86JS9qdc3EIwEqy2VV+YvScBPZaXtnMTna3IS9iCdk1324M+bR3EE+dOcvKuzkmqSLiGmzj5xTiIheePT3lu+adQaP//BXS8MMBXZJ4Zd8MUdQpYR+cq1uFaZYHdOlCUP43VG3M6wy8V4osugoo0ShqIl+qKVBcumtnDK3twfGAxwAQBAvjZ3blaNRZ0V49U/6tk+4B9REVSFsXRp7oIYZXgkaH2s7ikNqVmev3RN8apkgtOmhTAFCJKwf6i2y9uzpvjqSnPZtOdHJbPZ1X5l/uIYR40AAEZk9w4cGgqOXFVw5azM6YV2DAjgCWvDGUdLjsZyXfGquPqJAABO4t9u2yDI4uKc+XOyqpGEInTsHTxcrC8oNRTHm4bpwgABeHvI+4tma5WOenRufrUu7u7wJUcCQggAaDwScQ4La+6Nzw2Q5nwkKYSyDDafEPc3SveuxpdWflq9E0ESaCFspAyxF7HS9mZnm5V2AAB0Cs2szKoKU2ksTUd/YOjYaB0n8hkq04r8pTFetNPbc3y0npf4ZXmLZmdWx17PMdJCmAKOjtYV6fLztDkxnn/C2pCpyphhKIrrKkdGTpQbS2LvZI3BimyHt2de1qx4C0aBAIqSmKpB2MUphFF4Gf6zx/l/7fYv5Bt/Mys3U/F5TrqSmBDKEtz4tHfx9ZrCipTlwbicSUYIvSH47DaBxMGDawm9+uKNlOaKuBudrXOyauLaUDgcHD06WhfkQ5lK85qSq2PpvvMSX28/0+npJVD8upJV2fE0lWkhTHNBuZiFMIqXF3/bZntj0Puzquz/V5b1eU0CnJgQAgBGe/mjW0N3fNuE4Z/PO3MhSVgIT/fKr+4WVs/FblmGxzbDfqnijngUuCKumRQf6983eESv0F5XvCrGIjEKYTqyTJrLBROJPz6v4PA1lXsdodk727bbUhys61Inr5Q05+CNh1OZWyNN7IgSeH2f8PYB4Xu3Erde8TlXQQBAhsoc73oCI2W4s3Jd7CoYO2khTHN5Uamltq4se3xe/g/OjNxW29sfTk0AsMQQbAOpNcgPdSZTfNkN2vZ6JuA5Gw8TcozkS2WKKNFtTaG1KDLtT7nNC48vBP/4Lh8Ig0fuU8zISTfLF5r0HU9zOXJjjr75huplZvWSPR2/bbPFkuyQ62kWPclGFZ9os7sxte0423kKiomnnVLp0HkrVUe3hAAEAAAocEzryZRVDgDmzGEopDjaMn0kkaiVUSDHiG5bCiszHsnaF2NHp2tE/t1b/Oxi9NvrCWV6ivazIC2EaT6f8IPTRDcmUeRnM7NPrak67YvM2dm2xxGc5vyiykjdntRVEAAAFKWzuN6WFBrEM3JlnyMZC9VLVDwn9zSxAABUY0itTqMavRye5j7HR3JLHBCCDJ84dwJevr9NdAwnY1zsbcZNlmlP29kgPr1V+MZa4tYr0nOznxlpIUxzsSAFPEm2a+ORw6FI/b5pTytQkRuWlz42L/+h+qH7TvQ7ufNmVUQIElVpUzsoJHJnpNY7SmTly8m5HxEULF+nO7mbZsMpTiUPAEDVeplO5dSsHAmhat30550PFEMVynNUSZYjpw7gWfnJ1A3yDKI4b4xDAIAogZd2Csfb5V9+iawunL4phhwT3JGCoDxpJpMWwqmAXHwpSaGUUHLaJHIBJuMHAwBIQV8yV4/CNNXKkRRkTJVpf+Cj5+O95+eDql4MJZHtPBXLyTfn6FvWVudSxOwdra8MeM6nxuplayMnd6ekemdBEJC6/FAAADwzX05aqjNy8bI51PGdKc6CCwDANHopoSGmTPsDm16Y/H5JQS+mnT4O7RSolqyJnDow4SB9dJv6ihtBMutVZBlMGdopzMLHNvAMD372RdKkjelCwZ1vqK+8OfEqjYNpOZ6qF+3zQVoIp4LraQpsekEY7Y3xfL63ObDphXj7+Gx3Y2DTC6Izkaytkbo9wZ1vJqxDkIv4P3qB625MrHgURflc+uAGoTXZLKxEXql2zT2BzS8m6ZIaQ730en6gXRiNKf+fCkMfnZu/a1XFP3uc1x/s7jvXIhqEVKAqjehNyvc4AVSpScxbeM4HBiEViTVwgrV//OzdgtVq14gw3J3gfJ4cDtK1W4A8UeNRjV4OJzIiRDUGzYpbAhuemfDppKAX05sSq2QUTGeS/K7xrggp5JPDQSK3JBmz/Ggvln3e/cR2H/ztm3xZLvrt9YQitn28kZO7qZmLMF1Sqn/WVP0+yNBTj1anhW09zg93J1xcjoSSuXrKSQvhVFA1S/XrvyG6rYEPnxNGeqY9X1ExX7/+G6Jz2L/xWcHaH+tVKhfobv4a19fi3/C06Ilv6l59xY2aFevCx7bRBzcmsAwBz8wz3P4tyDP+DU8n7PRDlRrdjV9FFEr/+/+UAp7EjJw1pdYZ7niYaaplk5bVKLrrvxRp2Cf5XTGeP9egPH7tzBuydUv3dDzZ7Zy8hkZ9xY2JDQqFkR6m+ehkbSBLZ3N9iUwTCrb+wKYXBPtQAmUng1Cq4PZ/RU4diEoCTiArbtEe2RyUSGMCOo2qdVTFfP+mFyasYkU1ibtGMVOW7ub7A1tfGW9BDnpRXVJCCABQVC7guj/OtEwf2KBZlWxsVb6vFS88d5SoXpv8p3f59UvxO5bHOikoukalSEhRkVS2kyj0wY0ISakWX5e4CVkKHdgABYEsKE+kOIT0kS2JvURcd2OkYX8iF52WBDI8XTxcsMS8siiE6/b6Nj7Lj/TEeD59bLtvwzOCcySOq3BMaP8H/k0viIG4k/mJXod/y8v00W0whrSF57i0KNC1WwO73pTZODIJjycYDMocG9zzDn0s7hS4kwk37A/ueRfKceQdPR8yz3nfeVJi6LhKdYfYVfs6r9zb0RmcmKk4tP8D0ZNIdlNuqMu/+aXgrrckOvDxUUkK7Hg9AWtw7DH74CnB/XE6Q9eHzydmDULIDXb6NjzD9jZHfz2yOXjg1R5uqDNBc7Icrtvr3/zSxw+VLAe2v5Zw9SCEMsf4Njwjes/e/+Ced2Ru+mxz0xmV/ZvPpiHk+lrDDfuTNQhhYOsr4xPzQghljqFrt9a+ueN7/2Qa++J4SWWe833wVGLv9ScNyYFdb7K9LcnYEH0u3/v/FFyjiRUX3DbfB09xQ13xFpTCwcC2f4VP7om7YGyJebFHHnnkUxHYC4LNZtu8efO3vvWtT/tCCIoSuSWK8rlcd1OkYT9uyEA1U0VlRFCUzC9TVMxjW08ypw/gGTmoavqoKwiGk8VVZEF55ORurqeRyC1BiFhzVqBKNVUxD0AY2vMOgDDeeX4ERcmCcjwjN7T/AzngJXJL4p0g4XleoVIpZtRAnqMPbCRyilAqjtQZEyByilGSog9tVJRUI1hSEdEQDFMUVwV3vkFVzgcxR+81kfid9nqGZx/oCGIALsvQjt0PIqeYPrJZUR53+kBMb6Yq5uOZecyp/UzLcUytw3QmgCBc95kErIGxx6x0DtOwj2k+SuaVIiTFDPdQ2QUImcgyfExvpmYuFIa6wke34Vn5+dWm+oOCBnqMZbFGGfxk/RAit4TILg7tfx+yEcJSCBCE62lSlM1JxFrUJIYrKuYFd72F6UyY1sh1naYqk00fCBBEtA1gxiyUpEL739de84WkZgcBABByvc1IURVJkgAAKeAJH9vOdjQ0KFdvHKn8we1kZX4crrjQztc1q25HlYm/TQAAIMuBba+q5lxJFlUmbIPrOh1p2K9f9wCmjSM86VkgDJ/cxfe36278Cm7IjKtgpGE/c/qQ9tq7yOI4QjH/uzSEEGLYNPFaL/kQa8NP/mT50sUI/glH+4Q5MwTHEfIT0ZYhx0Bp3CIRBIk+Z4JjEHIcQBAgy1A8OzOPYCgAAEEwCKNFECjxCE4SeWWQZwEACE5E2x0o8FH/JEIqEJyQvA4p5IOyDAUeIUlF4UyZjSAEiRCkzIQRDENICnIMlGVUqY6WRZXqsy8hhktuK27OMX/zN9FqcJ2nQvs/kNkIqlBCgQMYAWQJIAhAECCJgCARFENVOoChgAkLAY9u9Z3K+ecNwSAHvZ7X/vSJVZoIgiq1mFoHJU7wubVX3KhccHXs34X9qf/GJAEgCIITmClLDHgVOcW6m7+WWJvif+8fgq0f0RoALxhu+wZuiS986wTofe8xrSdwc7bxSz+Oq6AU8HQPDz3Yw0BZegofLFGgZP4MkQ5EDm82P/gIZogjxOIEoCSyzcf44W5Mo4/U7c34f4+iyqQyFciREF27BUGx0OlDGXd+myxJJELx+OqFj++Qg97RHvYMfeOdP8wnqaS0gW2rY9vr5EgIVRsMdyTdc4UwuPttye+CkmC6N74Es+dEDgf9G56FGKpbdTuRNyNJa4JjKHRgAzRYNOVz2LaTqFqnXnrDgS7ljnrxR3eSlnjSgjGNRyCQ2abjmCFDv/7ridUH8lxg84uaVbfhhgy6dhvTcgzTmU1f+a84TMhS6OCHmCFD9e8mRfS72JbjXG+zHPQCFM98+A/g/DkORa+DPrBBtfhasqBiomGeFQY7hOFu3j4o+c5O1hrv+k70lRddo+Harcp5V00rgXKEFu3DgmNA9Dgkr0MKeQGEQJYggqquXKdZOE0wmkteCC9wrFHRY4uc3I1Qas2K9bEM1+RwMHxsu8yENStvibHdlHlW8jiZxiNSyEPNXKicfWWsdfO7gCTy1l6upU6KhLSrbouv6y3Los8hOq2RpiOyaxQvqTHcfH/spcdijcoROlK3h2k7IYf8GV//JZaRUJo9CIXR3nDDPr6vDRBk1ncfjfUjuEblSEiOBKVwSI6EIBuJWpNZmmk9abjlQeWc5fHWRYbgyW7H/7Xbfz8z837Sx4/2s81HUbXO9NWfxWtqMvxQl/etxzRX3qxZuT55a6LX4X7xd1RhmeGLKUjzK4V8wQ3PnBqqwWddver2JHYpAAAAgDwb2PJK5NT+3N+9k3zdAACB7a9Gju7M+e2bKbHmfPyHmMFsfuAXyZsKbH01XL+HnHWlpmohVbUYJz8qrgAAIABJREFUIMhHx8QTHdKPvxDrAtEogmPY9+ZfoSjqrrtbOf+qxCojM7T/vb+hCo3gGoECR81coFl1J6qKo9clBTzBnW8oKhaItl5+pA/IEhR4gCCKGdXUnJXk1P0GCMMnd0lBr3b1F6SAl+tvEUd6BcfQx2MVFMVN2WReCVFUoSiqAfhZ9w8UePrQRwDKmtV3Rn1Cosch2Pok54jotkqhoMyEAAAIQZ5dG4EgmM6MZ1hQrZnIKSAKKlGSAumg2ylHsA8xDftRvUm99IaYJJAOhE/uhhyjXn4zFvN8PuSYSP0+0WtXL1uLZ8aXGlB02yKnDyAorl52QwKbq6SAJ3LqgBwJqRZcTeQUx1s8FAqpJI5pOSZ57ERuiXLuygS8c6LHxnWeFj12gCBkfpmifG5cH0SO0GxHParSomodqtZhal2SS+PG0xZkv3qiP1dJvLC4OOsizl+RcNDt8yFGhI0vBpdcpymqSkHUE9E1Gu+DPQVsex1VtTg1plqOE7kzMFPcSWAmE9jykmLeStGQE/0iPjgiNvVLP7qT1KniG1V7X/0DlAQ8swAAgCiUyJh/T5ZlNoJqDdqr75jWiPPJ/5TDAapioXLeSiKvJF7Hg8TQjt98FdObiaJKZeVCxewrUDKOXGa239yPEgSqMwEUw4xZZG4JXlBOFZYDfKomNHJqv//9f+IZ+QhJAlkCGA4AwHRmzGTBTVmEpRjPLohRy9NCmDIE+yBz+iCqMaiXrY1FAqWQL3x8B5BlzcpbYpkajCLT/vDJPZBn1VfciOnNcdWQH+5mW09EPTAJyA/X18q216EqrXrpDXF1FaPIbJhtPhYe6lFm5qgWrEI1cc8fCCM9TGMtQACeXaQon5vkzrBPD0GGv2m1vdTvfm5R0brcizR1X8qFEADgHBH2vB24/T9MSk16nXlMwH9nn9hYKzb2yT/+AqFJNLNuSpDZsGAdEIa7ZYaOjqJwczZRUB6duJ22uGAfZNvrIccgCqWibE7s60WhKHCdDfxQF0Bx1fyrYl27ACHX3xZdyqtadC1uzo7xcpNJC2EKEKz9kfq9RHaRcuHqWJZsiF5H5PgORKlRX3EjSsWaJlf02CMndyEKlXrZ2vh0CEKm6Qg/0EHOmKWctSzu2ThZpo9ulXxORcV8qmJ+YpN54ZO75aBXOW8lo9Be5GmYUkWtm/7qiYEbsnV/mZevwi46Yfg0hBAAcGp/2G0Vrv+SIaH8zZcdUSHccYZqGZB/8gVCndwMa8qBkijaBnlrH6Y1xDWklsNBrrtRdFuhwBM5xVTVohidLtHusmAfQiilasHqGLVNZsPMmcOic4TIKVbOuyr2xYMfW0gLYfIII71EbvHUESLGww+0E7klSDyuAwAA19NEFlbEWwoAAHlWsA+ShYkuA4NQCniSWfExnos/H2EKCQrSd04NnfJF3lw2Y64hZd7XlPApCaEsgS0v+8rmUNVLLq7Pe3ECIfzgMNM0gP3X3aTmIlPB1CDL/GA719eqveauuPrQUsjHNB6R/G48I0e95PopltiMJ+r0gqKgmr8qrtVMaSFMc0G5rIQwyhuD3v88M/zLmpzvlGVdPE3dpySEAICgV9r8ou+m+w3GrIt3ivQiYUe9cLBJ/Pk9VLzzgpcPks+JGTLjElHIc8yZQ5gpW1E2O8Yi6cS8adJ8uny5yHTsupmvDXhvO9Lr4RMKM3tJoTNhi6/T7H8/KAmXcO/5AnC4RdrXKH/nZimtglOAGbPinY5BSIVqyZrYVTB20kKYJk3izFArjlxTWaFVLNjVfsQdX8RXX6pTAte5UqlPPg4MhCYarJhPGbPwk7sTiW3bGYChpELEn4OQALoDF5cqn+mVN9SKP7ydMCS3Az7NhSQthGnSTA97/hQdBIr8eW7+MwsL7z7a94d2ewwpfgEAAALwaFOyeT8msHlIjvHqsYCj4P2Bc5hbvk473M0PdsQt46NhcMqdYtHqCsB2f1I2vRz4R1vKEoB0W+VXdgs/uJ3I/veu+RPOi0un05yTtBCmSTM9P6+TptBCAMCNOfq6NVU77YGbDne7zp/UcAwEgEwKsUVSVkMAwDwz0uhNWbOrJUCQP4c1kkJW36mr3RKiA/EJ+UwD6Ez16M3NgozklqKYFMAWOXet3OxUHaDJOP3w6S3Cg2uJoqyz7eoQDRtSrf1pPg3SQpjmc8j/Z++8A+S6qvt/7mvT2/betUXSqnfJKlaxjI2NLduAbUwgBAiB/EJIIAEC+TkGgikBAhh+BptibGS5SpZlda3KalfaXWl7773MTi+v3fv7Y9Yqqy3z3oxk2Z7PX9LsvDP3tfu959xz73muDctR7X++Vko9XTeP35CuY49vLVxp0688GlaY9LEC6qXOaBYjvDONOjV8K7rdxAy2dIP+1CtuRbUs0/TqhV+a5TrZeZKgONt6Ohoa8TeciIDhP2vk8DXWEyA/eVXYs5FZnHO1U/1jO3msIJp97HgQKmIu5k0gJoRz0XXDHMncqJv1UTTqnMZsHUSY3Pj+KyUgQVTcmpEA/KY5apG9LSnoqxWyO3ozUhkGVGqDA33zXG4Goe+Vpv92ZdZD5V0/bh2d+2ySdTASiGbStpWDST6avWS+GXW6ZzZYul6v0VFVx5VNFhJQ2byLE+QHtTM8HZF7hACwIQmV36AuT12S/7mU0oS3ckqS4Zm3xHXF9MZFVw8ISCBhYlG88m1W/BI8dUlerGSr0tmYcQL4w0xMCOeibpL8S6V8diTcJ+b4EP76BfnyrBXOZ+blLvytKlnFcyli+E61/JtmLKiVwxc68JOX8HhQ5eEAQCF4vg3/uB4HIsuaTNHBphT01Qq5JbIpnxD5ZvTdFfQ3L8oDvqi97Q/kUBVjJBzVvzvVcmFH8SsDjgfPdbrEucYa29Ook0PR7I8YNINzo5oZFWIKBJsfMHU38X2tM4z+uj0zC7xq2V+fhO7NRF+rmB6gnuSJLeJ93+5IQeeuf8f3duEVCSgv7H1B/3BUNOrQxzZet6rklX764byodbAihm9ckL+1jDaGV8h3Dlqc5DvVslUTkaBeHCenw+4Yb8Qe7UyxCIkJ4Vx8LJv60VraIZCvVsjHw+iwHsql/ns13e4mXy6Xw0/he2IB9Z3l9Mlh8m8X5Y5ZBuAzwlLw/dX0XRno6Vr8yyasogf82yLqKwupP7bj713GLlXVyDU0fHMZ9Yk89HQT8+eOiDy6xTb0k7X04QHys4YoBDbjNfCTtfTPGrDScckc/Mdy+sf1cjgnmaXnTm8rytRzq4421zpnLRm/KwOdGFIzijk3SspmioKuT0ZVk4pfarcI/1kj3ziBV2BBHbPP6ml01LaHzGcPeLzO6U/eWAD+uUI+ccMro2WQ6vhHaRz6Win17xflaQ9q5P6RhobgNQ9cq4v0++Bj2eFexsPV0sA4+dxudlpL2t0QFe8NAAjAd6vlr5VSSRFvZvDOAHm+Df/POtqq1lWVMPyiEVdNkDtS1JydiOGn9fgvHYofewLwYid+pTuaswlXiNUjnAcEUGRBuzOoLjf8sgkLGIosc91+hGCRDe3OoM6Pkd8040QtSjfM/7gwFCyPRxuSqdd6yCvdOM+E4sIer9k0aHMqMrLw03rc64WlcYhS8nzqGNiQjEqs6Pet+MI4WR6PGOWjIzOH1tuChNH8qA5bNSgzjFOeEQrBuiRkYuH7l3GOCSVGFvViKNiZQb3YSVwCLJjzroVvMN2A9nWTNYnzW6MRujvVkqxlH63oStKyF0e0egamnRECqLFDoQXpFa5QzzCgTjc814Yv2aHIevXwVD16uUvemq7MnIaGDcnU0UHyXBsWr3nCEcCpYbItbdYHwmCmKRpVn/AuWKqlrnnsMgxodwbV6YZnmnG8FqW9u5xuJEBoBElqd900c2htIvWtarnUhiwcAoBTw2RrahRG8/WTkGdCBha8IvzgMv6/K+kwX6KmPrzvjPQvD3Om60/q3Cgx09LihIjdNwAAeLIGP5RHFVsjfYZ/04x5DP+yJNyzu5EeD3nqMn4kj7o7U42NS3by43r8yXzqnixld63VRX5Yi9clUbuVlHKEsOsRxoQwXPLM6K4Mqt+rRg4TwpNDloLViVNyuK8b55uRLWw5TNSiXRkUR8EzzXjAD4ttyuTQwMDGZJSqg980kzY3WRqv7HAAEAQhz6bZnUmVDZPft+JF73ZVKkjSoV0Z1Ks95NAA2ZCM6AhefwSwIRmdGyXVE2RFQhS0MEmHLo4TQiAjPLFfbNHdk2b9x5p+TPMGZNrXRd7qJ71eSNWDiUUAkGdGe7vwWoVb0yAEeWZ0ZxqVY4K/dpJ93ZhGKM+MWAoO9Yk7MxX3vzSCJXFTT/gf2vGAHxZaEY3g4gSUxqE5psqSMtjhbnG4W8wqmh6jzDOjHenU+THy5w6cbUTxWoQJtLnIwgj8JB0DO9KoH9TiJB1K0aNoCaGJhfJRUhqHvlklf3t5uOFHu4f87HXxi/ewmYnT2/DrZvyZXFGruep2yQQu28nLXYSXIUdJMaafN+ANySicsdcc8DL8+0V5Uwp1f9ie7o282InLhuG7K+lk5UMZvwQ/qcejAfj2MjpRyeE+CX7dhPt98PUltKLrFuLDUph3+5u+klXXVexjKTAyM1wviYBnlh0xbO922Y0OfG2GhTzL5D6PIYFDy+LnuSs9Xhj2YwIQlMHEoNXhPcoOgYR+utdLVsSjQ7unRvdHBvD3LmMDg6adi5lDoZvslYiIAQCCEowE4Ok16FMLZr39w3741CmZAPglYuOQWyQ0gpBxDKTLDU8Uom8vC3eTVQD46CHeLdMEwMQiEwu9XmLToAN3zfcAzsKXzsnNTjCxZCKIvloKD+eqMzPFj+vx6z0k3wR/3BquqhKAbg8BAAODuHe7jtB01Bu9+Mka+dS9rDlsuXGL8mcu9gwGxFc25KXruPpJcnyITASJlkYFZvSzBqni/umBNUXIBN7ux+dGSb4J/aZRPHWfxhSZK1I7SV7rxjoGlY/iryymd6bN1TqRJ/t/51iyUb9g2cwZnCKGFzpwt4e4RGTj4D9XRCpdBOCn9XjAR2SAX6yL6Nm4wuMnJQsHjxXQG5LDuhWSDD/YK6wpou5aOd3/HvbDt6vk5Vbh70t1LU5ybpR0eQgCWJGAtqVSitJcX+rECEGDnQDAU6tVnumQnzxZg7+5jErTo4P9+NVuAgB/2qrA2ngQvn9ZfiCH2vxuONQvwekRfG6U1NohIMPhu+fafv7tfvJ2P/73pdSM/kC7BxoncYMDut2kxwuYwK820AttAAAH+0n5KP7HRXRyGDHhUT+0u3GnG/r9MOgjo35wCACEfL6YfLIgttdo9MAEXuvB5aPk8QIqTPfi3Cg52IeXJ6CHchW4WE1O8lInTtGhvy2itAof/rMj5GA/XmhDj+ZTSn0pCUPlGNnXg2VCPl/MlCqphnRlr9HRALzUic+O4CQd+vVG9Z1Uk4M80yy3u9GGJPjOCpV2+n2kcow0OMiwH+od+I9b2AXh1TcMSLCvG1+Z0HKLIGMAAJmAWySX7LArDb62REGrCMCPWkZ+1jb24rrcrUlTm7IGZTg7Qr5VJf3uDrY03JqVc9HqIk+c5P+5lP14fhTkYcBH/rEcA4LXdsxjzTkuHfyDc/fj1vjUWaOybhG+dVE6PgxNe6KzVel/VOOXu3Drw9GxVrxPeiQfnlwRrrUXToiTHvKV+2eIe+x6W25zk0eyRJ2GW5mANqVQcaoyev67Tv5TG7Fy8HgB9aWFKkcPx4fIf1/GHA2TPEEApXHoI5lIkV94eIC80YsXmNElOxkPTuWV+GWSaUDrk9BHs6jM2be2HQ3A/zTIi21okQ0aHdDqIj0e6L8mhU0mYGJQphHyTajICuuTqSQtAECri/yuBX8sh9qYjCaD0OvDfV4Y9MFwYMoCL4OGBj2NQo0JSqBlII5DOWYoMKF0A2QZYZGNYiC26Xb0wARe7cGnhslnC6mV4Ulg+Sh5S7kENjrIX7twsg79XVG4qdtXODtCXu/FS+PQ4wWUivh9h5u83EUoBF8soVRMpHs8HqI1vdyFW53krgxqR7pKD2eSh9d6cIebpOnRYwVUvMIexCfBpQlSPUEcAiEE4jRoZQJak3TVq3tvOT7qebyy++vFyV8tTL5JP3HzNt2em+5G/uIx7/2ft2l0t+5aB2TQRcchhBY3FIddBPpim/zaOek7j2p0Mz2fL3XKuzMoVvRFeCP+4ZysZ5GRAUwIAWAoJGJiZFCKHpK0qNgKuWGECjfsl8wcWpOIdqajNYlzRbln5NwoPHBUyrfARzPRx7KnHLUwkQGS/ywm6CDTQOWZYIEFFVlhRTyVPl+Fuu9Uy79oxIusiKGAQsjMQpIe0nQowwg5BigwU7lh36lY9YnoEJLAsmHyN4XUqvAk8PwY2d+LF9rQY/kKBKnRQfZ24SRVEnhskLzdj7eloXuz1Mxg10yQA30kXgufU+6Ahuhwk983BimW+3wxlW1UI4EBCd7qx9UTxMSiR/NROG/4jXhF+HUzXpmAViei8OOWt5g+v7CnvLPQqH12dfbNKGf4XgkhAFw46p0cke56zIpuj2HHTcLuIU+9KPzTA1d3kLmRK4V5o/7rAQlGAmTYDxwNYfZIAOCXoGaCVI6T8SDR0rAyAW1JpcJ/RwZ85J0BMuAjDEKfyEcFZgWvZ6ODHOgjXpHszqA2hZ1oOugjL3SQiSB5tIBaPt8k1BzEhDAKhAKhn8gPVwIrx8jL3XhDEnpQiRdYN0le6MCLbOjRfIpV0oMQgNd78JkRcm8WtX3OWZzZONRPjg3h9UnowRw1TiQAnBkh+3txsRV9NMmXZFNZhqnbQ/7SQT6Wg6KVbn6bE5TxF6v7Ljv9r2/MzzVEvA7uet5DISQY3nnBmZjGrNrx3jTgFoBxaGqQ3jlnuP7mCWHkBCSoGCfnR0lAJo/lK0tGnQjC2/24yUlMLHo4FxWGnYzNy3BkEFeNEzOHHi+gwpnzAwABw5u9uHqC5JvQowWUQXkUPCaEUWDQR8LJ9rxCg4MstCrOtywfJWsS1SxacItQP0k2hje3fyMygXOjZLOqxUBXGAlAig7gQ1mPMEJ+2TH2vaaRP63N2ZkcdqAnDN5DIQSAoB+/+f8ca3YZcxdGWeBvE14vl7pH8FcfnCcl+nYWwqgwHoQ3ejBC8LkiZT3XkJ/8tZOMBsjWVOruzHA7nzYXebWHeATyyXyqNE5BlxUTwhi3lJgQquD0uPeTFV3/VJj8r0VRmzJ8b4UQAOzD0jsvOD+Q9Xs7hvCvDoj/91PcvIUGP/BCGDkdbqIoxAoAfgn2duE7UhTEZmOFeWPEuN3ZnGis2F68r9/xaEW3X74pW2bceuJTmXW7jcf+6uIDH5AzCsGL8Lt3xCd2sLFyu1FBqQoCgJ6BzxRSKg6cl5gQxojxXpKp505vK+QotPF4a49P1TZ3AADgDTqj2Cpe9Pt4l+rD80u12cWak6+4ybtSyIv+MXdvdBp3DZ7A5JgrCmYHJ9vm/c6+0+KCdGp5fqzP/AASu6kxYtxqWocqBenqTudamvrDmpy/yY1ff7zl5JhHnc3jDX+KUusAADCRK9r3R2Jh9Q4jAFx8tzwFQ3OXeo5FoWXXM+zsdAftkdup6zuFyVz+a3Mfru3Cj269XXORY0RGTAhjxJgLSRZUFw+ajWRLzumWvdM+/D8Lkv6yLvfRiu5ftI+psGk1JDl8I9FoHQCAjjP5BfUeIQAgCrY9ZO5t5jvrgwBAU4wsR68s1rt4AnaTNgo7ERi1Nt/sLrUgwR+PiU/sZGdcNTgvR+v/oLphMW4NMSGMEWMu7N6hgzXPRFcLrYZkCtF27+C0z+9MMp3fXvxc98RnLvQEFU4Zrsq7u6b7SPTaCHHGtAnP9BYqQqOjdnzCUvmO1z4sAQAghBVV8r0Gd2Bixlvg5Z1GrZI13rNg1sW7AxM3fi5jkRf9r56VCtKo0hw1veXlnmNZCQsjbuBVRPk2q2D0gSAmhLNCgIy6ehQdom6eRsaRlfL7QBAQlJV4nYMzLa+MuLqjZS3ZkrMq/+6DNc+QOUNnStlS8vGzLa/e+HmOgSvfXhyQ8dZTbYMBBS6UQWPx8a4oNnJJ1taG/tMRGrElMRvuNR3b6wr4cJqtYNjZqc6Oyz9xoPqXN+qon3frNVFYfGLWJ7gD00OsvOh//eLP2of4C63yJ7aqyYDlRX/vRFNR6prIWxhiYLI1Wv7ltcH5GO9B9Yn+/v7nn3/+t7/97bFjxzQaTV5e3o3fefLJJw8dOnTs2LFjx46NjY2VlpbOaOqmVp9AgBoHzl7sPKjXmK36pHAOqejYX9t7wmZMMWis4f/Q0brnusfrUqy5HKNkO16ASe/QodpnKUQlmDIUHRhCxuKB6l+JcjDJko3UlnVrH6mqaH8zyZxFEVajUb90rHHgzIXOg0mWHB0XacZ5Znxxddfh7vH67IRFCEUhwcyotVn0iUfr/1CUtjYqBgGAQrQoB+3eoURz5rQ/sRTak2mzC9Lnq3rXJxgz9eHud0eATPqGzZpEjotCWXQNo6vvL4u8E7cmMkKA1J/zl65MbBu9oM49sugT4k0ZBy8/U5C8gqGvTtS1j1QVpqyKsIUAgIk07OzMiCu68oknMHmg5le7l3zh9+8YPraeyVNe40IUxbLWv9xR/LCWNUTeQgDonWis7zv1kWWfj/AhFGX+7cu/1bIGmyFFtRG7d3DU2a3aAi/6r72PN4/btwzTk08+OTAwsGnTJp1O9+Uvfzk9PX3p0qXTvrNnz56lS5fGx8frdLq0tLTi4uIZTd3sMkwZcYXFaWsHJltPt7xMU8y8epOdsKggZUXLYEVlx/5Q7xnOrxSkrEi25FR2HGgZPJ9kyQ7/tdFxppL09XbP4InGPwsSn2LNVaRnFKKL09Z6g85zba+5/ONptgIVL1i8MS0ncfGFzoP1/WXp8QtUv/Mp1rzcpKUXOw82Dp7LjC9hafVdOUIoJ7FUy+oP1/0+wZRu1CoYlMyGUWuNN6Ydrf9DUeoaFKUNxJItOWdbXylMXU3dYBABbEowlpi1nzjfZeOYFbb5NmcEAIB4Y9r59jdy45dFRQgBYMTZZdUnahUOTUSZP1T7rEFjMeviQ5+k5HB9rYJzmHXpKgpTV6trjF5jzopfeKDmVzmJizlmamOS9pHqBdEQQpbWtg5fyE9eFvrvpHfoSP1zH1v1f8426lw+8shmNV32wESbSAILUqPQPADoGKluH6m6O2IVHHP1Hql77s5Fj6VaZ/BAwoEAqWzf3z1WuyxnB0Up3pJRxuKpppeGHO05iYsVHYgJPt/+hic4mWjOCv+oMIVw6nu3ElmWr/z7Bz/4wc6dO2/8Tnx8fFtb27ymqqqqVqxYEc3GzQImuL6v7NULP6nvKwvn+5IsXug4+NqFn/aMN4T/KwHBe6LxL29W/WLSO6K0hR0jlw5U/6qy44CM5fm/fQOdo5f3V/9vZcdb6g4nhExMjp5qeulgzTMu/4Q6CyE8Acehy8+WNe+VZSkSO4QQWZZONb10ouEF1Sc1jVFXz6sXfhJ5w64w5uora947xxda3YGSQw1fqu4VZHzlQ0zwiYYXesYb8A3ndaTu+TH7kNJm1PedfrPqFxXt+/28+9rPJ70jp5tfVmqNECLJYk330dcu/LS+rwwTTAgRgviVX9pffv2QCmvXwov+l8//95irL/Tfg5d+E6HBK1wxNTTZ8WbVLyRZnPTgr/w6ODKJ5z5wRmQsv3jme9F68Br6z5Q1/TVyOxc7395f/UtJFlVbGHcPvFL5o76JJnWHtw9XvVzxwxFnt4oDX6n80cDk/KIwDVmWBUGY92vvgUd47Yjm1VdfBYA9e/ZM+87TTz8dCATKyso8Hk9xcfFsg6BbVpgXAUqyZJekr/cEHWXNLwVF39zuF4Wo9LgFxWlru8frTzW9qGF08ab0eX+FobncxNKcxNJLPccv9xyLN6YaNJYwWxhnTClMXR0U/edaX3EFJlIVunc2Q0pR6hpBDp5t2aficACQJVyYvjI9rrCy462OkepUWz5Lq4mUcoy2IGWFhtUfa/hjUPSpHrcCAEJUTuJiDas/XPf7RHOGonj1jBg01gRT+pH652d04+ZAxhIQcqMradBYWoYqkszZGnZmny9ew3wqO/4PPfZnuybuSbMaGAoAEKD0uMIJd39t38mWwfNjnj6zNi7kt8UbUy/1HMtLWaLovJIs2UVpa/Wcqbr7SF3vSXdgPMGUwdCsjjPW9Z1UER2lEJVqzXv3ffnrmLs3M7Eoq0BXd0RvTZGtceFtNDkTNMWWpK0/1fSijjNZ9AnR8gjhXeeyY6S6ceDMPcv/nqLoPx6VFudQqwrV7ENf0f5mTvzSJKuaOYtp1PQc9QTsdxQ/EokRURaO1T+fYM7cVLRH0aN7BQKksv1A91jtR5Z/wWpQvBGSO2A/XPd7mmZ3lX5GUZDG6R87Wv88TbE7Sj99JcYQPlM6dzsX5q2urt62bVt5efnixdN95M9+9rOLFy8OBAK///3vN23a9Kc/zbxG6tixYz/b/+XU9KtXJzktwWIxA4CGNYT6nYDgQQAEQMeZAAATWRD9AEBRTCjAIsmCJPMAwDBah3+EF30YywAEAK5IHSEAiACgkClBClj0SYmmLFEKyli89ueCggcAEMVoGJ3bP+oK2gnBghQ0am2JpmxRCgAATXMhkRCkAMbSDIcjxNK6YVfH0oytH13+1VAbusYvlbW+dO3pE4J50Rf6N8fqKUQDgIwlb3DSGRj77MYfzzEf4w1OvlL9wxnvfkDwOP2j24ofX1/w4GyH38ifznyL02gQokOXdMLTp+VMX9jyi/AtXMvhhv/nDIzzos8dsN+x4JGlWdvV2QlR2f3G5d7jCcaMPau+EYmdEDU971T3HvqbjT9kw57THXP3NAyelrAY6oMwwXrObNUnWXSJosyfad376U3/PcfhmMD32ydeGnT/ZUXrhdDfAAAgAElEQVTaMsv0H53w9reNXPAEJ1lak5Ow5GjDc1/YpvKyhxh1d7cMn/fxzhRLXuPQmQdX/GuEYwi7d6B+4BRClGvQILZs+cinLDpV1UWuQICcad0rYVGQ/bsXR2cc/EbNT5PNWYIsbCl6FADah9BfTlHffETmlGfJ+AX34Ybf5liWL8/fcW2bfUGnl3dQFJ1kyg7T1OW+Y4RgltG6g+Mb8qc7DGEy4ek/3/n6lqJHzbqESf9wy+A5F2+/W8l1m/QNnWt/ZWXO3WnWBVc+9AvOnomGIWenwze4Z/W/UbOkXhKCa/tP2H2DmxY8rGFmHvB5g5Mjri6Hb2jSP+IMjN9Z/HiiKVuU+Yvdb/Gib+OCh68Ew+dGwpLLP+oKjDl9Y96g3cM7vLxjafadq/J3zX3ge7YZYGtr63333ffss8/eqIIA8Nxzz4X+8cQTT+Tm5n77298uLCy88Wtms7m7TH7kW59mQM8AhxDasGFDamqq6lZ5g05e9mlow4xjFj/vruh4U8bSxqI9em7+XDVe9F7sOjToaN9U+FB63Aztn4224Qv1/ad3L/vba0e7xZlrUxNyAEDHWvSzTNsQgmv7TnaMVK8t+GhmfMkcP6HX6z++4d+mfRhvSB92dl7qOWozpK7Nv1fRBMD9K/6J0zMAgAm+1HWUodlFGRv0+rAmt25k55K/GZhsudRznGWYeHOyajsAEBA8LM1YDPEByaXRa2hQPMD38a4xd++Yq9fhGyFAMMYMzQ57WovT14dpIUe/MCflukGJX3C7fOMO/4iTHw6Kbo2GoeecFv3+sqzVia4Hq/p+ujTj0azrFgxk6YuykooAQJSFrrHLohwIys44U5rCs7xKrn5RbsoiAOgZb7jUd7hm4PBdpZ9RbQ0A9PrCzKRCl3/8DffPhES64uBdu58w00xEWrh7+Wf3Vnx/0jMUybNxLe2jlenxeduXPAEAGMPrFeInttJWs5qoxs+PfVqUJC1jOtk2RCEKCCFAKIoxcGaLPjHZkhtmm58r+8aos0unMWfGl9xZ8il1Z3qg+n+7xmspxOy7+BQA6DhzXsrSzXkPhWmNEHy04Q8D9tZ4U9qplj/7BRdBQBEEABrOkGDKSLXmr86/y6ifuUcamGw91/pKXtKy9Pj8C71vOH2j7sBkkPcQIBSiCSIEY0RROsZk0sfHGVJykhYlmjLT4gubB861DFVuW/gox2gnfaMux6gzMOENTriDDj/v9AnuGROkKcToOKNRYzNqbWZjQnpigUmbmGqeP6r03niEnZ2d27Zt+6//+q9Pf/rT8345KSnp5Zdf3rp1641/umWbbvOiv7ztdXfAvm3RY+G45wTI5Z7jHSPV6xbcN7cgTaNz9HJD/+n85GWLMzcraiEB0th/pmO0ZnnOzuyERYqODTHi7KrqPmzWxm0ofIBRnqvi8Xj0Bl119zu9441rCu5V14YQY+7eyz3HKYpeV3C/6lQXURZahyqGnV0IoSVZW5PM4Y7BQ/Ci/0TjC6GXzaC1JpmzkyxZcYbUaGXKqKPBFXjgXOf96dYfLkmnZ4ldv+ebbs8DgRP7XJyO2vTR22uLdkEWuHcf+5O1clW7/K8Pqcw56hmvizOmU7Imwhvx1qVfs5RGxAKFKArRSZbsNGt+ojmLphQ4MP/7zhcMWltWfPHizM0pyicaKtsPHKp7NtmctTR7e0naOptRgZsx4er/8cEnLPqEtLiSeFOyzZiaZMpKNueY9QlzH/in099uHqpIMmdRFKNldHqNxaS1GrXxVkOiRZ8Up0+1GZOp8C7C7Vt9oq+vb+vWrV//+te/+MUvXvv5mTNnrFZraWmp2+3WarWhzLdDhw49+OCDfX19iYkzZGDeAiEUpGBlx1vuwPjGoj1hLqJoHaqs7z+9LGd7QfKK8H+oZ7y+ru9UZnzJspztShcztA5VNgycWZK1Vd18yYiru6rzkFmfsGHBx1RIIADIWCxvPjDu71mdd7ci4Z9G5+jl5sHyOGPq6vx71CWOYoLbhy+2jVQhRJWkrb+SB/iBwSHIn6zokgn8dX1u/Exhu9tdCAFEgRz4nWPRWl3RSvWThTcPP0+++bzwtT1cZqJ6n5VEu/qEjKUxV++ws3PU3UsIxgQvytiYmxjuZLCfd7cOXxh390syn2orWJi+YbZp6Rlx+cdre084/WPxpvRVubsVHTvi6q7rPcVLvhU5u8IPjLkD9uruww7fyIqcnTmJMy+fC4fbVwifeOKJvXv3ZmRMTSPn5+cfOXIEAO69995ly5Y99dRThw8ffvzxx0tLS3meb2xs/PnPfz6b43izhfBc22uT3uGNhQ/GhTcOahmqbBo4uyRra0HKyvB/pd/eXNX1Tnbi4uU5O9RJYFHqGqUeZAi7d7Cq85BOY16/4GPqhEeShQudb4+4upam78pPU5YPfQWM5crOA6Ou3pL09REuXDvZ9GJOwqKcpCWqV0be/siEfLN+6JV+x2sb85dap2vJ7S+EAOC2y28959j5SUtixm23e+fLp6UATz69M6KGRV0IowUmuGe8vn34oigLVkPSuoL7FI19R1zd9X1lnoA9N2npkqyt4fumkizU95/utzcnmDJW5e0Oc85PxmJdX1m/vTnelL4m/14VfdTtK4RjY2Ne79VtRFiWzczMBIDR0VGO42w2GwAMDAx0dHRotdqSkhKLZdbMyZsthN6gU1FobsTZpSL40D5SnZ+8XEUqlzfo7Lc3l4Q9UzUNTPCFjgOr8u5W5wWGaBmqjDemJZozI6lHKEhBp39UafTyQ87efsdXavp+sTzzE1nXbbb5vhBCAOhr5c+/7b3/8zat4Tba32rCTZ78i/BfT3AWJRW5b+S2FcJrcfrHzNp4FWsBCZCu0drmofMFycuL09YpOnbE2XWp5xgheGXe7mRLTphHDUy21vaeoChmXcF9NiU5q7evEEaRWGHe24dYYd5bT50z8GB554Pp1h9cM2X4fhFCAKg67psYEu96zPqeTrxex7OHxGQbum9dpFmE7wshfA8RZcHuGVDqNvh418XOt9cvuD/82GysMG+MGB9wllh1F3YU17oCd5/usAvvvx1rV24zEAI1p3zvdUOm6BvHzf34rpXvWS79hweW5lQEzwway9aFn1Q0QxkmMSGMEeN9TBzHvH1HwQqbfvXRlstOf9TsRjtOJI7OoHaIgq17zO2XAwMd6isS811Rq0i871jw3rWM5rabtYxx04kJYYwY729QQPqOzPxwSfqusvYXeicjN0gE2XlIZZmI2fBWDAGeQV11BmrrHsuZN91+j8q6Gf7G8ciaNkXbIB6dwFtK1ewjE+P9TkwIY8S4hRDwVgxF1ySlZ4MdjodSLSe2Fj7ZOPSNpjEpsol/xNFEkIkYzbJTmhwL3ztzpd+UbLZkte7kqy4VJaSITBAdnU7stbPSTpsrSsamI3vUu7wxbgExIYwR4xaCALGUrzpqpeRDmDZnes8NLLboLuws6fILd55qGw1GVA7esCrVVxPNRmqL4oKts3qrS+8wUBS6fHrWyULJHgg0zVA4V5rwMwlRWIzY2Is9AbLCEr3Y8jXwvS7fxeGbYTlGtIgJ4awQQZZdSopBEyC8ygLcMW5PAk0TnrP90bVpWJkijvv5npndI3WwyQZxIoCDkpWl967M2JFsXnW0pXxCfa1jLsMkDLij2EJKy+DgrOk8CMGWB8wt1YHRvpn1m4nXiaM+f/30KKg45meTolDt741y6f51NH0T/EHsE32VQ+ZtUVsa5DndP8eVjKGOmBDODkLeyiHHG23SeFjjRCJh5+Eu5ztdsldBGAQHpclXWrwVg0RWHM4KdjqcBzokh8pK09K433moM8Kgjedsv9AXaY+Jg5LrcDf2ReTEhOB7XY4322SnkhHM7OgWJnAZZvtLTbI7OgZDWO/K81UNq75xM2LeluU50w8AFILvLEz9zaqsB8u7ftWhfv6MyzTPFsxUB5pTC/UmauNHTWWvu0V+5hfBvC1bGvdP00Jp1McmRZpDWN+NgyJZHi/Slhl2FhVHfMKAR6VpTBwH2q33LYjK7g4EE8f+djbFQGkjzWv1Vg7568YisYD9ojCkfqQ144Txe8h7UIYpitzcCvU00ubbtAU2f+2o98wAY9XO+J5c+31dUTybYvCeGww225lEPaWb/3lFDKVbmACAPGW94rCXSzeFP+fBxOm4bLOvZsR/aZSxamiTsnXxlIHlMsy+84O+qmEmQU8b1Syr12Sa+V63u6xPFiR9hsp9QRFDsckGb/lgoHGCSzZG8p4zVq021+q9MBRotnPpJsRGmvvAWLXaBTb3sR4iYjY5OqXGAYF2QZzzzTZdUXy0prgoHRtonNBkmEWQOY4rNGkfSLd+o26gfMJ3V6qZpRT3xGyywXO6X1esuPCNOO4nQYnST0++RDQSh7xsyqzX0BLPOCfk/nY+u3jmF02Taw00TWBeZhOmxM/fOK5fHFb56zn43TviR9YwiQEvpWOuWAYAwsueU33SmF+3OBEpv4CiKPqP9Js2pDO2cKuUzAH2i5P7WsybMzXZ4ZZmm9lOQHK+1aHJNOkWqb9uvovD/suj+oUJiFO+GF8mnlN9fI9Lk6usuyCYeM8MEBEzSsp4vQ/KMEXOLVtQTyTsqxoRBtyGFSmavPnvHw5K3sohyR4wbciY482fhjQR8FYOIpoybc68sR+JYvOmH87LnvIBccRnXJ+uyVH5mk3WDUK7h0szGdemgfJeIwT2ie7TfTggmbdlR9h9yF7Be24A0ZRpS2bkcggAvppRocdpvbdAxcs/I7Kbd73TFfdwSbQ2g5O9gud0P7M5+co6br+Mv1jVV+fyv7ohP9846zBOHPGxyXq4YRdv59ud5q1Zih5FuPLwTwQ0uVb90iREv2sWE8eBDtv9C+Y4VhLI67+ZXLPLOJsWAoD7ZC+bagwptONAu+2jcxmcl8Ze/NIp8b+e0PgqBjX5tin/koC3ckgYdFt25tKqClAQQhyVfRpOa1ihuHTfjYjjfvfxHtt9C5Tei2kEWuyBujHrPQWUQaUd2cm7jnfrFibqShSPkAAg2DrpuzRi2pzFpSnbaiDQYvfXjpk2ZnAZynbtCHNBfcwjDAtEIS7DpCuJF/o97lO9IJO55Q0xlCbHol0QF2iye8oHaCPHWOfv1ik9qy2MY5P03vPKfKNrm+c53UckwiYbwu9eEUNpcq26hQnBVru7rA8IhC/eV5D0yLosHfOy63iPNOrnMsxXe8CwQRytXRCnybP5qkd81SNMgo42qNz+jeJobYGNtmo8ZX3imF+TYbqxo1cEl2pkk43O/e2MTaeuc5zeQg1DmzXeiiFtgW3+b1+DOOwNtthBJpSeudahpDg62OkEC6sxTw2ZWQo9kGHFBJ6o7C4x6wpNMz+EfLvDe2E42GoXh71Iw9BGLvTwMPE6X9WI0pF76OHXLUwgguw50893OGibljawgFCwxT63i0nRKCGVPf2Gu3C5lmFnvl+aXGugfjzkFwbbJnVFanrkKzx3RNy1kslMpPz14/pFiYhGfI/LdbhLVxhn2phBaVQGJ8QRn79z0rYlJ5K2hQh2OPzVI7YHiiiN+hEYEbHrSBeikOWuPJUjOUI85YPBDof1IwUqQiOyk3cd6kIMsu7OVxS7Esd87iM9lJ5VNyj5sHiE+7717L999RsAQASZvDsDgXmJ8FO52ISXiISvfi4TSssgCuGgRDChdAxCCPtEgoDWs5Kbl70iQgghRAghMkaEACAghGBCCKEQIjLBvETHa1mbHnEUDkpAgNIxRMJYkCmORgwl+0VEI5BBcgtExsTLs7lWbbaFBCQs4lBLQAr9QwYJUwb26j9EmYiY4mi+12W9p8CyKzfUeGnc760ZBQDiE4hMgGDZIwEAkWUSlKdMYUJpGckekD18+g+20dpZbz8OSu4z/YCB+AUiEZCJ7BNDDZMnA5IzmPSZJVolwZOxw20csKG7IHsEvt/FJRuSvqig/sa1+KpHxBE/3+skAcl6T75WeYDuWryn+72XRzQ5Vtt9EXkPAFNuDebl+IeLo+LJ+apHJbvPskvJLhuYiGN+cdgrjvqwIAMBRCHapmFTjIxVO76/JfWzy6cdUWH3ffx81xM58f+5KHW2+k0AIHuEYNukOOpDFEIcrcm3ek72Jny6NJIxBA5KvqphcdTPpRmFYY95SzYTP09oq+IdLx/AWx6Yq+Sn+2Qv0BT28da7C1S3rW0QP39E/N7faCgEjlda9OvS/ReG2DSjcW16JDc3NPHPrE2yLgirXs0ceM8PEkHWLU+RxnxKB0xXEIa83rP95h25TJwWAIRRrzzq1y1R0DZhwOMpHzBtypzmyWEBC0MeccRrWpM+W8IJkYnnbL/sCFruzp9byyVHUB7zCZNBQ2kiZeSwX3Sf7AUKWXbmIkbZDAL2CpKLl9286AwwaQZ9dtzc33//byZEgGIQetfTpzQ08270AOk5Sj913SkDF4535asekR08Mk59k7FoKAoBANIxlIGV3YLv4jBj1Zm2hRVtC7bYPWf65KCkK85mrFrGzAEAoSnGpgEAoKiZo38EfDUjwVZ73EPFXNbVvgBjDAhoMwcW7sppIiNHaWkAYGx6oAAI8V0a5budpjuy5lDBdy0CbeHAwlFaltHRAEDH6cRxf7DRzuVZtAsVTiFgYMwMoTkKIWHYC5JsWJeuzMJ11ggBQCwCxFCmSN0vjAkRiDgc6VZeRJD9DePYIwR7nLIjQIc9VxFsn+Q7nTiUVEwBQggACCGAASQ50O5UJoQUYlMM07x2aTIgjvj8dWNSzwy5S+viDRd3ljxa0XX36Y4X1+UmzOLo0CbOsDJlyqAjGGy1B3tcgRa7rmSeAnJzNVbLmDZlAgDf63Kf6QcCcXuK5z5k1Z2G156ZHOwU0vNndR3M27JHf1nFRJYyevCC9JHVTCiQ76kcAoSs9xagCByvEAPfPUOxNBfHBiQacRRiKIRQKGMAsTRlYBEbVrc+/HQFDkqUlvXVjpnuyFDTFBkm/lwn2QPAoPHnawEDANBmTls032DkXUhAdLzVJft5xqx1vd0hewQiEaAAZEAUAhpoq45LntVYoMXurxrWLUqgjZz3zIDkDMguQfbyRLi6aBS9O8xCeoY2cbRFAzLxVgwJA27LrlzEIHHUJ7sFyRWUPQLxCLJPxAER+ySQCQkl3SCYij9hCH1CaWnKwCE9S+lpJoz41vveI7w1c4TYJ7pP9QIG846ccFJggBBfzSjf4zJtylAURgg02/2XRw0rU7SF8wxhbvjFKfk0bcq8Vj7DR7IHvBWDtEVr3JCuIjUgtOn2VPtXpWoXqBy9AgCRsLdySBzxmbdkRbhKLNjhCDSOs8kGw5o0FScVAvvFQLNdGPKATHSLE7X5NqXuQmhxepjdX4TMsem2TMh/NAz9pXdy34a8NXFRSvy5OQx0COff9jz493H0LAHSyOkbxz9/Xfzh32qYkPDJMswXQAuTQIcDMSgQCGgRBwSIhIkgAwAOSiATLsMU5kT+5L4WYGlEAcXRmjyrJseiNKopuwLjz9bRRlazKMm4KiWsvut6HAfafReG2WSDbmmSNsfKpRogbOfMd2ls4k91TJyOyzDSJi1j09BxWjbewCToKP1cLRn+8QVx3Mva9EAhSktTegYZWNrA0QaWNmkYC0fH6SiLluLmb0ms+kR0wLzsPTcgewXztuywQttqBYnvcnovDGkXxF0ZkofPlPysSNEWKZRPAJjKKxlENDJtyVLdWTsahnC9U1uopv1XIDLxnh8QhrzmrVkRrQ8jxF83Hmi164ri9UuS1IW5ZK8QqB8Xhr2UljEsT2ZT3x+VBOatPrF/yPl3F3u/uyjtSwWR5lveVE7sc1kTmBXbbpZg//agmJOCbtIW29GtPkF4me93891O2SMgADbVqC2MmzfCfC3SuN/fMC45goxVa1idqjTDXBzx+S+Pyh5BtzhRVxyv6IXie12BunEAMG7KCD8DThr3ey8Og0yM69MjGQ3HhDBiCLiO92CfaN6aNffCiSsEGsb9jROGVSnafAX+kDDk9Z4fYBMNpjsylE7G8N0ub+WgOvmEkMyXD4SyNFWMFkOIw15P+YBsohN3FqifTCLEVzMa7HSYNihODLvOTCiBtt9tWJWiNMtjGr6Lw5p8W2ha5X1EOGWYOrz8w+Vdiy3a36zMNiicfbll+N349d9M3vd3NpMt+vt/TrjIky8KT/+tRqu+Fudc3MQyTJgIQ95g+6RheQptVTxrIE0E/PVjU4q4KkVZ+gkhgZbJYKsd0ZRSfcJ+0XtxWJoI6BYmhC+loQlmYcCjK0lQN6KNCWHEEJA9vKIHhe9xqVh+4KsZ1S9LUhG4kyaDwY5J4+pUdfJDJOw60m3alBFJDqS/flx2BY0bMrw+r/p6hIQ43mw3rEqNRAKn2lM7xqYZ2cToF2p5vxBmPcKAjL9U3Vfl8L+yIa9olmzS95zaM/6JIXH7xyNaOTcjL54UNSzas+lmJUnc/vUIpYlAsNNhXJum4ljZK/guDkuTQeP6dGULIQjxN0wE2yaZBJ1xbVq4K4YJCbRMBhrHmTidaVOGovhwTAhj3FJihXlvExQV5n22a+Lb9YO/Xpm1J0P9nO7NQ5bIK7+c3PKAOSU7mrWRvEHy788JT3060jL0c3D7C2F0IETdKFyyB3BQ4tKV9RjisNdfO2bZrSCzLFaYN0aMGPPwd3kJb29e8PXawX+pHYiwZsXNgGbQqjsNVcci2MprJk7VyisKqJungh8i1E6FMPE6pSoIAGyqUZEKhk9MCGPE+FCz0qav2lnS4g7eeaptOLKaFXOA7SrL5+aVakWB9LXNtdcr4RXsBCvJcKJW3rXi/b9yLEb0iAlhjBjvZ2QZhEjVy8bRB+4o2JVsXn20uWzcI569GJWmXYtYVqHuQIRgxTbDpVM+mN1fFd4+Fb7BylY5IwGlJ8zqygiHy5Q0MMYHgZgQxojxPobwAr//aOR2EMC3F6b+YU3OJ853/4+kFZvaI7d5HRyryG+7luwiDZah/+IYtjtm+LPCiO7R6rncQeILKDUY4wNATAhjxLhF4DE78QeiaxPpdXRBjlTTEBVrO5LNF3YUvyazjzSMeaRoFtdkigvklk6VByNYsklf38gKh8vghlbJXX10XmaYllr6sYTJopxZ+z2xqo5ZsVhlO2dH7hvCYzMUFo5xmxATwlkhPA+SkgKYsYFkjDlBRj3/+uGod4jMsoVSRw/xRae6eqaeK9tWlGTWrzlY3+SOWsVEOi9T7lZf4jh3kdbjxJ4VW/h3Tk37k9TcQZeEu4Xs0Rppx3JmjgQPMjZBJanfT25G8Mi4VHmJSoxov9wrELeHeKKcPRQjJoSzE+D5N44IR8+QYFghHex0B/ceECsvAcbzf/vKUWN2ft9BuXdQRQPFqjqx8rKin7sWub1bblU7SA+BsdTcEfkIgHi8ysYcc5iKkh4AgNw/LFbVRXF8g/Q67Sfvk6rqpeaOaNkMobl3u3DoVNSsUei3dy37Gm/ferJ1X/9M0UgVUFQktVgpCkpW61paaTozVbrUeN3fBBFxYS2umHCR9iGyvmTWVWjE40UWNdsTzgG2O4VTFZo9d0dY/CSE3NbNHz6NNJHuviv3D0t1LRGZkOQPkh7HyjDNCtJqmIULkNUiHjsrN7bR6SlIO2dhXp2WWVwEhIinzuPBUSojFYWxdSEy6JmFC3DPgHCyHGRMJSeE/8LQacmAsXjyPO4dpNJTEKssEY6Ks+Ixu3i2ijhcdFoyUMpHRQjhcbtwshzbnXKCTaNTuRMScXuEo2flrj46KX7uizwv4vka8cJlxNBUgprd5q6FspggEBTeKSNBnk5LjkpHBgjRC3Lllg65u5/OUbWN8oxWWRZECQ+OUmlJgiBwXMTbpSBU6nbsSrN8oXVyMCDcmWyiwj59PDGJWBZuKDhMJiaRXosMKvc6sCTQ59/2LLwnG1dfouLjkEEHAMTpxg4XnRtWaPRApZydRC3Nmz0ueq6KWb4I6SPa3vaqNVFk/UHh8CntI/dEZRdT8VwVdro092yPyBrGwrFzZHySXbdc9SMtNXcIx8/SuVlIr3wrBkLEc1W4d5DOVrgpPyFieTWiEDIrWHfxYSnDdIsK83p94tmLhBfYO9ZQcWEU5h23ixWXgKa5LetCb2w4yO3dUn0rlZLIrluuSJbwxKR45iLIMrd9I7Ip3oZD7huSauqBZbmt68Nv7XUNGJvwnTzPMQy7dT0Vr3JjMxIIihU1eGySXbGYXpCjzggAACFSc4fc2oXirNz6FRCeuzAHcnu3eLmJWZDLLFsYoakrSI1tUlO7ds/dasYfs8C/8jZ391YfwdFZx40x/+oh7/13PVbRLRN4afaaFdOPGxkXz9cAQuyqUioj9ernDpd0uZHbtkF1i07sc6XlcsXLueDeA9pHPgoMLZ6+QBfnU0nzRx15Ef71d/x3HuMSzLP2/vy+g5qH75n2IfH6pEuNzKolSKeg0yeE+MbGmWPl2kfuBYUj1BmsBXn+jSPs6iV0fnYkdvDgiHCqgtu+kUpRuc0s8fmFo2eppHh2w0oVh8vd/eL5anbtcqUnInf2ipWX2TVL6YIcRQfGdpaJPiTIi+erid3JblxFpc5fzYu4PWJ5DQkGuS3rwtcnuXdQutSITAb2jjVhxnymfi4QFCsukYlJduMqKk1xXWzi8ojnawjPs5tWU/GK9xnxeDxGhp1SspWLlT6v17SDSLXNcns3SoznNq6KpBPBI+NiVR3IMrdlHbJGGvKSmtqly43M8sVMifoCeNc1b3RCOH5W88BuRT3sHJBAUDh4Qty9WZEQEpdHOFlOJSXQ2elUatK1wiyerqTzs0la8n80DP21z/HqhrzltrD9OUkSLzXingFks7DrV4QcQf61dzQP7lZyTtfR3ybUnvXd+1kbtjvF89Wae7eHb7CsTq7rlr9y/6y+MnG6xep6bvvGqf96/VJtE2KRhT8AACAASURBVB4aBZ2WXbVEqXJgf8C394Dx0fsjD2PikXHh2FnNfTsUeUI3WMHC8XNAgNuxUeXYixCxogYPjnL33KniiSVOt1BWQSXFs+tWKPJE8diEcPI8nZnGrld24NThHxIh/MaXv3xk/9sAgCcnQx8Sl3cqtcznx6GZpwBPBB4AQJBwMAgAQDDxTyUCIK8fWIZoOOQPgkyIhkU8jwUBtBwVELEoEg0HgohkiVAMYAkEgQR4urgAmQwoGMQyDhkhGg4QQkGe6HVIFAETomGRy0dAxqN29u4tdFISAGC3BwiZapIsY18A3p3ZQgGe0BQAQrJMCMb9w7ovPcEsebd4G8bY7oKAHweC4A+QgAB+HxZl8PgJlsDrxxgTnx9kmYxMAIWMT39z7quH7Q7w+DDPE7sLBB4HeOLxkmAQ9wwSr1f/jS8pkkPP4LBBlLHXR1wesbGNjIwziws1D94dvoXr8PrFhjapug4oxD18L50QQVEnt1c4VQEOJ72kiFleqtoOwJRIS80d9JISdlHENX4BiM/Pv3GE27lJUYKG3NNPHG7QapBOi/RapNWARoM0HABIdc1Bt8e4aY3iljjdcs+APDAMgSDBmIqz0jkZVGaacOBYyEna1+/4h5q+ny/P/GSWspgzHp0Qq+uJx8uUFsstnZr7dgKjMrKHZXjpJxP3f8FmtNBSbRPhBTwyrrlvZzjHfufP/Ce2sAuzZtUA4egZdsViQlFyfQuedAFNsWuXqUucIYLIv/yWtGODMUXxeHQaYuVlPDahuedOAFAdPMCDI8LJ89z2jVeH7xgrsib3D4mnKtiNq+i8rBn+LEnAzD5glWXhdCVxuLmPbAtr4uNda8QXEE6cA4rS7NqsekCMMZZ5np1v1uZ9v73CP6QW8C8fICwDABTHglYDAIhiwDQ1dKUsZrAAACCbKXTvKbMRGA4AKJMOtNcNbYIvv0XGJonNTAFQBgPQiEJTIWlKy2EJy01tlMXErF4KDEPF2QAANCxlnnkALh4rF85dICJili2EoCD3DSCzERBF6XRgMSMdB3odUIiy2gCAspmmHiZCxKo6ublT+8RDdObVyJLU2ikeKycaltJoQMMinRY4jjLowGJGFhMwFBVnBYLkvgG5s4+7c/3c1w073fyLbxCNhjLogGWRyUjpNGAxA5GxjCE7XalTSF4/EuRYymhEei3F0thkoIvVe07Bg8ex00N8AUQwQER5/MhsRAj41m7aH4xUCBGiSwqkumb+Dy+zP/pWRKYkWe4ZkDt7iCwHnn3J8K2vhH8olRCHAZFAkDjdeGScBIPEHwReAIQAIVx5CZQLIbKamWULr8R+8fik3DsgNZ0WK2s1d20Gs+nhTFuxWfvAuc5aZ+D7penhbxFPJSdoPrINZFmqbRaralF6Mrd2udLmTZmiIauI620RFq3VMUsXev/zZ5r5nvMQbQNYlqFkdhUEAH7/MblviM7NZFcsjih+IAi+f38aaTUkOQEiEUJB8P38OeQPAsf5G9rokgLNx3YpNiJJwb+8jp1e0GoCf3r1ysd0fJz2cx8PxwDhheBbx5E/SKelSDUN/NEzxOkBAEQwECAUQgQIQxv++XMzKqvU1C41tDKrSyE3S25uJ5Nu7PIQt5t4A9jnQzN5YYRCuk/eJ/cM4PFJbsdGZDaBJOFxB3Y6wOsnXj/2+onHCwEeB4PEH5jyHxBCGAMmhKYBAZIxEEIYGoAw2zbA6qVzn+b73iO8VXOEfuFkOWDM7docVliAELG6Xu7u5zavpZKVDPbbe8SaenbZIrpI8ZZ6UlO7VNfCrl+heBYaAACI1yecKEcGPbdtvYqxZ2jTbbl3UCyrZJYtvOrIqkJqapcuN7F3rLl2KKDKkCycqSQuD7drc4RJEITnxfJqPOFQek+vWgjyclef3NkLQR4QorLTmZIFyBjlQhmKNt1Wil2QHinv0tHUi+tyzWz0qyPNS28L33QhcPcTyuahn3lLLMygti+bs8FeP0TlXsiyeL6GIMSPjHE0AxByvxDSalCclYqzUplpIfd9HhzuwEv7kc2E9Hp6QQ5TmDuX1zVbW1o7gi+9hWxmds0ydu0yFe+1/5kXcFcvlZlK52VRycl0chyVlhxmS4R3TvFvnaAS4ymzEZkMYDIgs4mymFG8hYqzUvG22drj/cYPAADF2ZAsA4UIx1KcBmk1YNQho4Ey6ECnQzYzZTZSJtPcd+3DEhq92UJIeEEsq8BOt2b3ljBj9OoECQ+OiBdrqfQUdr7By43I3f3iuSqmtIhZqiabgwiieLqSBHlu+0bV81WegSGuqoGKs7KbVkWSAIJHJ8SzF6msNBXXYRrS5SapqZ3bsSmcZIo5IF6/UFYB/gC7YxOlPBcJAOTOXqm2GRl0dH4OnZOhOjYYDjdVCAFAIuSfLvWfGvPuvyM/zxDpBJhSRIG89JOJR7+WwHDh+qQuH/n2H4WnP6fR3ZzSgzNyY/UJwvPE7sR2B5WWoiyhDGO5b0huaic+PzIa6JICOjtd2WyZJEkNbXJXHzA0u3ppOPkN1xHKPmtqB62G3bAynGzBa35aFi814J4BKj2FXbss/HxXub1bqm1GRgO7eU0kQ9iYEEYMxsKJcuL2ctvWh5nqEvLnmCUlivIpsN0pnrtIWc3sptVKJQTbHWJZJYq3cXcoPhZgagJc7u7ndm1Wvd6ACKJYVhl0uUz3bI8k74P4A8Lxc0BRmrs2qxj8Xovc0y+er2FXlKpwrK9rkscrnqsiQZ7buj7ydJtbw80WwhC/7hh/qml47/q8OxJvdaWhg887lm02pOeHK2tvnpc8fvL49mgWcpqXm1SGibi9UmMbHhoFhtbct1Np8ggRRKm2CfcMgFbDrltBJSp75YnLI56vxmN2uqSAXVmqbJaxd1C61ACIYu9YHb6U4nG7WHkZJJm9Q00GH8SEMAoIInZ5FDwrGEuNbUypwpAgxsLpSm7jahWzwXh4TGpq57asVScbhBf4Nw6zG1bSmWqKc4aQGlrl5g52+0YfS0dSj1A8XYknHNzOTcgUUd9BnG7h6BkqI0VpctqNyK2dUmcft2Wt6qVv7wm3RggB4Oio+1OVPT9ZmvFYdqRLNhVRc9JHCKy80xDOlzGGf/0d/88PcnPssn0zuM3rERK3R7xYh8xGNXEXQqSWTrmhFQx6bvsGRWmxxB8QKy/h8UlmcRGzMNx0MxLkxXNVeGScWb4o/KNCxIQwxi1BlkPhjggL82K7U/UCxGl2kMmgaNnJB4xbJoQA0OQO3num4zO58f+xMLKpXCUMtAv15/1hThNWt8tHL8n/9sgtjIoCwG0vhFGBeP1Iw6nJ58RYqm2m0pOVJeViLNY0ELeXu1PBUtQwhfB9nzUa4z0mGltmAEBUVDCKdmKEw0Kz9vz2onvPdvT5hWdWZjFR2XxnPuLTGPtwuJWnTtbK25a+B0k9HwbU53lRFLN8kYqj2FVLVP7ivLZvkt0YMWJ8GEjWsqe2Fg0FxAfOdfrlWbe9tXtItKpZ6AwUzSCfa35zIw4yaCcrC2JCGGMeYkIYI0aM66huVyZZBoZ6c1N+AsfsLGt3CDMfOzJJuoZV7g5/LWNO0jOKrQmMc2L6D904x3OqTr5jMa0iRZeQG8s9xfggExPCGDHex9R2RUFdpjHmJA6vstQBBqHn1uSsjzdsPdU6EpwhbpmbgrpHo9DUBAuqbsfmeNo9OV2pDl2QvIGrzRYkKG+St5SqcQfL6uUJ9/s4eSKGUmJCGCPG+5hJD2kbiLIWbl3CnG1Q7BAhgB8vzXgk07blZFu/X5j2V70G+aNR3JBCYNACa6C814dGx5yEZcCouzpJeaFVLkhF8bNvsT0bvAgOL0mxRXm+M4IiVDFuOjEhnJXYgxvj9mfbUrq+Bzs80XxYdRpACNx+NTa/VZL6xfyErSfbem/QQoiSsqwvoYfc4PdcJ//HL0vbll6X+neyVt66VE0y4NEaaasqP3IOKltlpQHnGLeSmBDOSs8I3lsmNfaGO9zuG8OvnpWG7Mq6j85hfOySHLyh0wiH8iZ5wqW+B+wZxXy4yXczI+PYVEq4XOrELf3RD2MCwH3rmLcvStG9EVuX0meUO4UhvlqY/E+FSdtOtvVdr4VGLXiDURBsiwEFCRX0Xb2Ylzvx4uzr5gJ7RrEnQEpzFPdvTi+hKbCZoukOnq6XZRlWF0ZBXP082VsmjTkjvYzeIOmJOFL9QXIVYkI4K3mp1Me3MBwDr5+Typvkee96VhJ1/3qmdwzvOyO1D4X7kOWnUqsLqbJ66Y1ySem4fuUCuqkPv3xa6gj7567FoEXvVEn7KyTV0yF+nuyvkN6qlCYj80gqW+TD1ZI6F+RaHB5S0yFHRRIIgeY+HMVX/f+zd97xcRTnw3+23O7t9abeu2XJsuUidxtjOpgOCS20QAiQhCS8CfklIQkJCaRAGiGF0EsIYHrHYLBxtyzZ6sXq/XrZvjPvH2dsWZalKzIl6PvRH6e7vbnZu5l55nnmKdVFJMLwzGal3z3D64eOhjOX0Bs/VmewTZOeUDWIJCS3ukdQScDxzYKU9ZvbBoUjW638NLJnZGbuvSiH9H2yBZRVaBtA8wqOWso+qNdOmkclEM3xXl2CeuTxeLdWNXGwYu4MSMGuYfTqDu2cpVSqLSk5XXcQvbpDdVkTb2TQg5/+QEl4F153ECWmH9cdREkuNcdjNqA+JnpGUV0nMnHEmkpq2vhRjKG+C7X1o9Jscn5hrGn6BRl2NGveEF5WTmU54xij0Y9r6tHy08hlc6h486yJMuxq1YZ9uDKfnKJIzRQIMuxu1bqGxPnFXOz3O4Egj3e3oVE/Ks4kFxXHfReH6R5B9QcRQlCZTxbHUSNhElr6UFMvoimoLqJyUmZGRdDQIT3+5AWU1TiTakf7IBr24tWV1EwF1AcieHuzdsbiRKRCkMfbmrRnvKO7VP/WU0qdDA0Asgrv7VPPWjIDYsY3qr78eOCa250A8MZutaaMGl9ul5fwD/8t330NYzHE9w0PeXHbAErMv2YCGONwJLK5QV+UmeC0Oqo1gA/3axjDSfOpZAZNIILf3qtV5JEVeQl2SVbh/TpVQ3D6IjoBd9xhH/5wv1aeS1YVxNeBAQ/e2qCV55BVhXEmoZzNLDPjDLjxx02agYX1C2guhrxC7QNofxdyWYmVc2P14VY12N2mdQ2juXnUgjh/8qgMMHPEygqKjTOzCsbQ3Ida+5HDTCwvp5j4F6tgKNTvM7b0IaMeVlVQRn2CEzZ6FwQBK+ZSUxQTnxqEoaUPtfYhkoTl5UntoBUVGntRzwiiSFhWnniXxiMp8EG9KilwxmI63l9qCt6v17KdRKaNj0sQDnpwSx/KSyOyXeSEzry4TT1zMa1PNCuLKMN1H/XvDYfeXFVa6KIA4MWP1QtWzoAgDHq0Fx/xn3OjAwjY06advuioNt/bp3UOoW+cFfc3+58P1UtW09RMmMk0hJ/9QFg6V1+UkWxzQR6/vktbWUHmpiTeFAbY0awNePCGpYkPubqDqKFbO2sJ7YjfdBwR8YcHNI4h1s6Lb5vrC+OPDmgOM7GygkpgY/tlF4RBHiQFAYA/AggBQuCLIABQVYhIBABIMogKAgBRAkUFAOBlHDWF8SIwOiAJEGXQMyBpIElIz5CiDBiDqCJ/GM5fRhMkIasgSAgAQhEAAFHBKgIVgaIAx0JEAk4HIR5GA/inV7AZdvCHQdFQIAIagkAYqRgCEQIAApFDjWACIiLWNPCFcVjEd16udx4n1XP0Br0hECTgZRSKEKIKgoQ8QRj0YgOLf/zVWHMAijIEBOQPQSCMet3QMYgIjH/4lfgKCxxOsdbWr21rQiEBL5tLLSlJcHMdEfH2ZjQawA4jPnVJ4vV+eAnXdaJBD7aZiJoyMl4VYUKX9rajUT9OsRJL51AJi4fD+EJ4S6NmMxKrKhOZ4ZPywlZ1abGYnR6fRshLeMCNe8dwWMCKCowOclPJ4gxCVmFvu3bqwsRFFwa4dld3p1e5mctfVkbt60QXzoQgDPm0Nx7zm1dYgwJctJIeb6TBAD95VLr6VF1pVnxio6UP8RJe+En0vSDDqB+N+vGYHysaVBeRuamxNqhq8NwWZVGhXJobU0LUKWjqRY096NxlSW2YxgL4vX3q0jKqMFGpPOLDm+rU+YVUAqokQvBxkzYWwKcupMxcHANdUmBLgybK+JTqxHdjXxZBeM/TwZoVKwkEkgocC6oGqgZRdY0igdMRAMDoIFr/i2PJqK5j4TBBAkmA3UQCAEWDlQMAeG2H5g5jjEDDoCNBUsDAAJDA0ARDAcLgCSGEYV4BzdCgZzCrA5oCq4EEAJsRSBI4ljR9UoDh7b3aRwdUQQaXFUhM6HRAkqBnCRrAwAFFgsVAEgTYjBgDOM0kCWAzA02QQ350oAstKyfzxs29hh705m5V1YChQVGBZcDAEDQNRj1wLKmnwWzEHEP2jiJPCJ28QJefOtWY84fhH2/I0aNFvQ44HcGxYNQDBmLAjfLTyPNXxLdg3fcCryIaAAwsgRAOCnDmYmpRooLwyU1KvxvzEkYAd1zCmpKqJAiv79Le26eW55A3xq8lHMsTm9QDPdpvr5uBCkSCDA+/Iysqcdv5cXSs/iAa8iKEQVKAIgFjwBgoElQNMEBTt/KTK5L6viIi7h3FvWOIl2BHs3bv9UndqYLw2Vs65pj1l3OZz29Vbr+YTT4yIejV3n7S3+gwnbVYVzPnqKW5pQ899YHyy6/F3edvPyjWlB1aqTEGjoVUG5luJ1KsRFw2wBAP9z4vMRSxaq58cnXiNmpRgUfekQUJFBUIAkqzqPNXxD2bEII3dmsDHpRuI8eCyB/CqgYkBXYzccMZMQ25qC1UlGFuHukPodEA4Y+gQASiIZsEAQiBjobvXsBMquc19aL6g2h1JZXtInxB8PAoFAK/gMIRIiiiiAgREUuf+FQdPtO94mS6bwx3DaPTF9HjA2CCPEQkFIxAkAdBQhGJCPFIVqLKAJZVIDDICCgCSAoUFWgSCAKvrIAV5dOMhy+8IPx0TKOH9ybr5sdk9MMAe9q01j60toqO63ipaxhta9Iq86n5cdpFAaBzCO1uQwuLyNLsRPZ9UXsdQnDqQjqBPLpRjdAXxu/XaRkOIknvgFE/fm+fuqCISv58pXMIfdyonbaITn79lVV4r1Y1ccSapI+RAhG8o0UTZVhVQcUb6yYpoGpYzxCTGvE+zaTbMRJQtGXvtXy/LO3rhYkUND4W/5i66b/Bs29wHKsoPPiaUpZDnhx/ftHGXq0sK5E0NBMY8R1ykJFlWccwdhOR7SKyXGS81RCbe7WNH2tOK7mwkKgqTNAC8e5e7Z1aJd1JVuWTJRlkdgoZb6GaXz8reQKQbgeHhXSYSJsZp1jJFAuk2aefmI+8o9Z2qJlOgiQIjMGgBwNLmDiwGkkLh60m0moAu/mI5nCY2/4uGVkwGwiKPuSXTlOgqcAyYNQTLA0sA1YjqWcwx4DdRBpYMLGkfTLj2ZdFIzzRglDVYEeLNhbA66oomymmBat9ENW2owVFZFk8AskTxB8e0JwWYnX8hrLoEXROCrF8biJn6RjDjhatbwyfvihxDw6fP7S/zxDk8WkLkzLjaAg+qNdkBZ+W0Gn8eGQV3q1VLQZiVWVSLgZRGrpR3UHtnBo6xmFwPHpH0a5WpGcgxk1VvHwOBSEAtIelVZtaXllVvNSZrLUQANyD6sevBc+7cWL5p8+kBu+kHK4+4Q/jfjfud6NoiBRJwqkL6bi6N+DBDd1aiAebiVhYTCZwPucJ4dp25A7i4kxiYTEV7yEoL+G97ajfjYozyUUl8a1OgQj+uFELCbCygsqOuRJW1FWiewSV58btKjGBWUGYLAjBtmZtyIvXzovV22LAjXe3aVkuIq6YobCItxzQaApOqopbFYseQesoWDc/QbERtV0keRRfdxDVtQvnLDMk45MNAC19aH8XOnnBDPiktA2g2g502kIqgYVjAryE396r5aYQCVt64RN3pLZ+lGojEnDujZ3PpyAEgFcG/d+u7as9rdyRgC/W0QwelOu38GdePbHSyKs7VH8EX/Xp1uCdlOOVYUIokfrZUXwhXN+FvCHM6mB+YRxy5TCHfaoXlhx17BIjUe8/EwfLy6m4jttVDfZ1al3DuCCdiN0nHAM09x7y4FtRPr27/qTMCsJkCURwkIfYDZuCBHUHtWVz4oteEmR4v05dN58ysHEP665h1NCNTl6QoGIREfGrO7WybLK6KPFVediHP6jX5heSOfZIMvUIAxH8bq2W6UzWpgoAggRv7VHT7DPQFADUH0RNvWjDMsqUnPb28na1PJeM14MjAT63ghAAbq/vPxiWNq4sSrKdrkapq1E8+VLr+CcRgv/3b+m7FzAJSIgZ54TWI5QU6HejhP1RZRVqO7T+MVxVkMgxSjSuJixCVUHc4zkqifVMfI7lfWN4b7vG6GDNvLin4awgnGUa0CdOFskw4MbpDoIiky3M++F+bVl53FEfx+IN4ffrtDOWJCu3AAADPPeROjeXrIw/QclnyOdZEMoIL9vUcmtxynUFSR0WNu0SAm51+VlHjbe97dq7tdodX/msraIA8CUozIsxNPWiublkAlkLvCG8vVk7eX5MQWiHCUTw1kYt1RafvW22MO8s00ASM5D+MWuGdt9rq2Ymu6PDTFy8emZGNQFw8Wp6pgIbZgEAhiQer8k/eXPb6enWLC7xXQ8f1AzmiQNmU5128oLZ0oOfEgQBCUflO8zE2TVxT1KrMZF3xcgXaas7yyyfMrNScGbxjagVFu6W4tRv1fYm007Ij4zWowpQDHjwsA8nc4g7y5eZWUE4yyyzTKR+K38imu1rl5GK7yhPbwgIbw0HE24n5NNMFrJzv3T4mffr1LXz4vaHnGWWKLMDZ5ZZvqgg7UQd8KsyPlGNE8CSxH0Lcr5f16cl6qAQ8Kj2NPpwD3kJ72pFJ82QdT2KLGJJ+AL7T8wSF7NnhLPM8hkgI607EuyM+Hv50KAQHhQiYxLvV6SwqgQUCX0iIWwMy1G0g9GnscZsg6nAaC0z2+danGaaAYD+DllToaBiBnLcTCC7hOnvlHNLZ7jlw4LlnEzrH9pGHu/2XlvgjLcRPogommA58nBrWxu0efnkTCYxx1C7ObLwpBkIeZzlC8GsIJxllhMOwrgj7K/zj9UHxpqCnsaAp08IZXOmQqM1z2jJ5sw1jvQUlrMxrJlmLDqGIg6ZavyyFNEUnyyOiHyfEHp7uPsv7fuaQ95MvWmpM32VKyvHncIedGYWzrCrZFq2bs/7kYQFoWdYNdsoZkrH3V9VZn5tZ/dV+Q46Tr9D74hqTz2ycGEM79drN5x5yPWGD6GRPqVgblIivGWvUFDBTt3/uNAU3Nsmn4gtyywzwqwgPC69rZJ3RC1byHGmmAzIA51yyK+VVOkpXRzzp69dZjkiNTsRD7qBTjmzgCESNW9LAmbjyYE7S1z08qGd3qFd3uHd3uFa36iL5aptqVU215W55RVWZ5HRposlrngynUTDuDXk3eEZ+sjd/yvfTjxMnDNceEVp2UpnZiLO7JNCAK0DRcY6JpEGzTZq34eRggp24sDGR/JJrnSZco3Mc32+y3InJoiZGveQ4sw4snDVdyGjnogG1XmG1c794sJ1SWlyvlFVU3FazoxF5Us8qt0cqVppmJHW2vaJGfk6sz0pOzBCIItIb5g9GjvErCA8LrllbEY+03lADPm10gWc1TXNyMsqYkI+7cB2nqSIsmo9G9sgyy5m+tqkHW+GXJm6onn6uKSajiH2bAobLVTJAr0u/nj8/nbJM6xmFDDZxUxi66dnSO1ulnLLmJSspFaNgw1iViET4zf2uUVG2l7f6HbP4MfuwR3eIYxxjSN9qTPjJ+XLFjvSbLoZ0wYogphrcc61OK8rqASAA37337Y237x7UwBJX8ube1laYcVMhK/ll7O9LVJR1TGJIGOA0RNLTzO17BU8Q2r5kvEZwI86dfteadrdzUNxC8JBtWjekV69V6ueupACgK5Gye9Wa041JRMUpKm4Za+w7PTEI2InEPRojbv4xetNCczQCYgRVLeFzy9nk5SC7kG1o16Yu9SgT1Q0CxHUuEOYW8MZzInM2bEBRZVxRkHcZoyxAcXmopP/Jo9lNqB+ejQVdzVJniG1sJKNZcUXIqijXlRlXFKtN1ljHbLuQbWvTWINZGm1no5Hpwz7tY79IkZQskBvssU9Q6KfSzNEabWe5eIe1hjBULc83KMgkOctsyWmYkaCqKdFCvs1RxpdMJeNS6Uez0CnPNyjONPp7GKGTkiVOQwep7tMgV+RtrkHP/YMbhnr3+cfLTbZVrmyljszVzgz843HKaB1AkAa3vVOmFkkPDnU/ER34zJn5vdKF61LzYnlvUIEDR6Uc0omsQTu2RRevD4pmTo2oBxskKrXGqON12+JzFthJD8ZpAhD4esHXlpVtMAWx5L89O/d595gN1mp2s2RlArDH1+Uf3s927pXMFrIvDnJ7jb2bIokvL6PJxpQHxxlBjrlRetNyWfU6++Qh7rlBWuMienoUVQFN+4QdCxRvoRLbO+LEHTUi5GgVrHUkIDpmA+i1lrBYCFLF3BxbfpDPq15j+BMp4sq9XFtdGYzy8wwGENfmzR4UM4sZHLLpp9viozb60T/mFpazbkyY9W8g17tYIOIMZQtjG82KhI+2CgG3Fp2MZPAiREfQu31ohhBpQv09rRE7AQjg0F3Lx0OoPxyNi03QQXRN6r2tskSj7KLmcwCJrGtvW9UHTwoSyJmObJgLpvYojbSqwx0ygDAmci0HJ09lT48b3v50BZ3/zb34Bb3QHckuMSRvsqVudKVtdyZEfVhOZaDDaJ/TAMAZzqdmqvjjDOv+yoS3vN+uOZUky8SeMnb94fWvTaGvXPusjPTC6Z9b8in9bXLkaBmNFN55azRcqh7Ddv5onn6GI8GjofEo30f8SULemhc/QAAIABJREFU9M50uu6jSNXKI4IQAH7eOBhQtPsXxCSzASDo0d543PfV77oAoHZzpE5iUiyQ4hdLFnDj7aWJ0d0skSTEMrunBWPcuCtAU+ycxcmVEAPQFHxgO29PpZMU833tcn+7VLXKePj3jZfhHqWrSZyzkEtgiVAV3ForKhKqWGqIS6WTBNy8mydIonIpl8AWeVYQToLMI1ECABBDKkKgKiDyGABkCWkKRgjEaPFeBSsKBgBZxBgBQkiRMaOnNAVjBIqEIyF07o12KaJqKkgiViRQVKSKWNNA4hEACDwCAEXACOGgT1Nl/JXvushjtLWgD2kqkiIo2ogsIE3DfAjJEvIMq5oKF90Sk9Uo7EeSgCQRRQJ4pFv2e9TUbLomfvNOJKi11kq+Ydmeqlt4cnwHLdEUa0jDPS2ye1BhWaK4Wn9s+o9YiGqZQ90KSUHRPL3FkaAhKOzXBg7KkSCiKMgqYmPfjoxHCKOhAWnXwOheYagBjdZrw4jEK12Zq1OyVjgzF46XkNOBEfjd6kifwocQRmC0HhKxCfRqUvgQqt8aqVxJmC0mhPHGgfafN253MPrfz19b40iPpYVIQOvrkEM+jWGJrCKWMxK9bfLRts2EwNCyV8AYJAFVrTKOV49aQ+L6zW19G6piXOHaaoWhbmXthRYA+Pi9yDOt9EV58rKTjElKawCIBLS2OrF67Ux4imLYvy2iN6ml863TXzwlYwNKR704f7UxGSVVCKPGHbwrS5c/XVm+48GHUNNO3pZCF1fFp5ABAGDoapKGe+TK5Ya4jLpIg479Ysinza2J1VFjkka+JILw5X+PrFi+XNMIjEDHEIqokTqCIECRMaunFBkTBFA0IUuajiFIkiRIiGr0OpagKQIA9EaSJIHSEQxLdtQJooiQBhQNBEkAAEkBYIKisapgmiGDHo2kCJOF1BtJggSGISiaoBlgWJKiCIYjSRIMZgIADFayvVbqaRVFHix2CgPQOow0AgggCIw0gtYRFAk6jqBpQscQDEvSDLBGgqZIUUAjPXJhhT5vnPNbf7u8f1sEaQRBAklipBEYA0lhAKB1JKMn9ByhYwkhhMMhVLpAX1g51aDng2jziwGMifGnNrSOoBgQAtiaQq05Pz45+sbjHqxRAEAQWJGxwONlpxrzKxI5YQKAba+FfGOayCNFxF/9ftwe9hPY92G4cYdYPJ9ddkasNzUmCTs8Qzu9Q9s8g3u8I7kG8wpX5nJbZpmaGqmlhTA+94b4TraOJejRhnuVnmbZaCNWnJXIoVR06ybxSIggIYLECBrtV1VFPfWyQ31DGD/W0/TTho9PTcu7t2p1KhurBVISUF+b7HdrvW3yhd+0J9C3YxnuUd5/LnjZ95wTdg5z32p8vKZgsSOmvm1+IZhZyJRW6wHgtw+EaSN521UcmXSVLVWGF/7mrl5jcqTTAKAqR4VRSgJOzaaNsR1zKAJ+77kAUnBeJVm5NHFBiBHUfRjxe1Sdngx61Ixctnpd/Gd6GDoOiN5BJb2AjQS1oEcL+1VRAJOdXHt+TKZ7pEFrrcCHUNVKg6LgkF+NBHDEr/Gh6KjTkEaQFD79Svuk5t+xAaXzgFQw94iVSFWBDyE+oAphLESQKGKZ10QBKwKWZUwQGAhYfpY55NX62uW5NdykO0WkQjiEFB5JEuJDWJGRKmM+gjQZyzKWRaypCGkEAJAkLlrAls6f5qv7wgvCT8c0Gt2bhP3anMWxWixHepWeFim3jE3Pi8NOGPBorXsFq5MqXRi3Ed/v1jr3i440OjEv7eiIF8Kocnki1v+oRqjKuHGXoGOI8sXxnQFMQBZx0y7eZKOKE3LWmNBU3ZZIXtk0BltBU/f5R3d7h3d5h3d5h8ckYZkzY5kjY5kzY5kz47Cry1i/0tkgLTnFSNEzcGLf3y6P9ivVJxnj+q2bdwtR0wUQoDeQBhOpN5KsgeSMJMsRxybdDqvKL5q2P97d9Lv5a76WNzf5bieMENY400Rx8v26fidL/1/59DorxvDM793n3Wg3WilJgdv/Kf30CibGEmnTdqxpp+hIpxk9cfi3IEni8EmzxTFNNMhhuhvFpt2iM50mdWpmviE1W5eYc0fDx3zjLsGWRpdU6XPnsPEW1I2y7fVQV6NkcdKOVMpko2wplD2NstjjaOvZP3pIEgwWCgB0DMEZSc5IGMyU0Upa7JTZTtLMcef5m4/7/WOq1UUBBowJACAITFLAsBSjJxiO4AwkZ6L0BoIzkZyRNFhIABAj2gsP+AxmktGTJIU1lSBJDARoKkHroiY6gmYIisI6ltRzBE0TrIFkOEKnIw1mQseSOj1p+aRucNwa4b59+zZu3Bjjt3Pbbbc5ncnu05PnUxCEGEN3s+QZVEqqOaszpi2hb1TtapTsqfEJJIlHrftEkoTyJVy8i6zEo6bdAq0jKpYmuDsePCj3tslzFultKQla6kKhkH+IHelTKpZxSZ6B9bXJg13y/FUGfdJnaUPdck+LXL3WeKwXj6ip+wPuvb6RWt/oHt9wW8hXYXUtsafVODJqHOllZvuxoQjdTVLQp82UH3zLHoFmiOQl/QSOV32izj92ze63CozWfy061cUmbe2cOV4dDDzQMfrWmpJprxwbULa8HLrwZgcAbKrTWvrQLRs++9KDk4IxDgUjckQ/0itLIgYMLEek5TLOjPjCJkUe9bfLvjFVxxAFFfoYl6DxaCoe6JTdQ6qOIYrn6xOYm+5Bta9doiiipDrOt2MY7JL7O2STlSpdGIcPYMKuEscStyB85JFHvv71r7Ps9Gu3IAitra2lpaXJ9G9GONGCcPCg3N8hF1bqYzxeCge09jrRaCZL4vGJUhXcskeQRZyAKoY03ForJqzGAUDAo7XsETILmJzSxIOyAx7twPZASZU5YTeZKJKAGncKzvRk/QIAACFo2M7TOmJuzaFF3yOL9f7Rev9YnX9sn3+0I+yfY3YstKcusqcttqdV2VLYY09xx9GyR2D0RGHlDMgtTcV734/Eay2IkSnKMMlI+2nDtmf6Wp5aetZqV9aMf3RijElq2ZsNnvMXTDt8az+IaCpecqoJIbjjEemms3SFidbkO9EcW4Yp5NNG+5XoVE2gQYlHfe2yb0xlWCJvDpvAhpUPoYMNYiSIUrN1eXOmHuyTIIRR5wGRD6Psorjd8YIerWO/iBDMWRyHI70YQZ0HRCGMiucnvkFPpAzTypUrP/roo2mbpqgvRYp334gKBNScFqv7eNiv9bTKVSsNcelz4YDWskcoX8zFeAIxnqEuua9DLl/MJRZXpEi4YQfPcuSSU0zxzorDqApu3iUgBPNW0VZbUst6V5PkHVarVsbnVDYp4YC2a0uQLBd7ad+j+90HAu4DAXdYVebbUuZbU9akZH+nZGGl1cnEdtuaims3R/LLYwqemRaRR/s+jMxbbkgg1iVJGJK6t2r1utScS7e/9pPypbcUL/iUOzApKSxtoMheXs4zTLO89rRIK842A8DuNs1pJj63UnBSzHYqmfg/1kAWz9cDgCSgnhY56NPizftjMJOVyw2AYbhXqd0cpnVE7NlCAIAzkZXLDRjDUJdc+0FEbyRLFuhjjOWwOKmF64yKhNvrxYBbzZvDxiJK9UayYpkhGr3WslfMLNDllrLJV46blCOC0GKxZGXFtEksKipimM9F9csTij2NjstJwGSjKpbGbXEyWamEQ7XS8pgEglIPo2m4fAmXZHaJ/g65qEpvMJOhUCiZdmo/iGQWMIvidFU9jF+RWkPe5qC3JeTdO+Bu4T0e4MsO2udanPOsrluKF1RaXIkF9kk8qp05ueUbUdvrxSXrTUmGOSbDGen5207+6oatL7WFfffPP2nGktEkwRyLvjUoTi0Ig15N5FFqjg4DvL5bvWTV59QoeqJhOTLqK5QgBKTn6dLzdIqUiH8IQUBmIZNZyAS92sEDYtmiOFY8HUvMreEwgp4Wae/7kUXrjLFINYomiqv0xfOgr0Pe9W74BNlRZp1lZpkZkqxQHzu8pnaEfR1hf3vI3xH2t4a8rSGfiNQys2OO2VFmtKdL1tUlaYUma+yBDccj6NWadgmLTk4qivkwvW2Sf0yrWmE4QbvaKDFWqA8o0oXbXnWx+idrzoop2duJ5IY9PTUO4w2FU5Wtr98S4UNo+Vnm+oPoxW3qz6787LYSMfA/X6H+swIhiGu0zlaon+WLDQYYFMJdkUBXJNAVCR6M+DvDgc6w36dIRUZrsclWYrYvdqRdnjunzGzP5E7IiqM3kEtPMyUtTw+RkqVLsp6DT5CaW3u9faOqJ6wJMqlqYGR1NqM101E8Jy/DFsdGxKpj31h9wVe2v3bpjtf+u+ycKWShgnBA0VzsCVwrMvS6YVGZ+prOBmnl2WYAeG2nek5N0gETs3wxOUF7tllBOMtnjKipfUKonw/3CaGeSLCHD/bwwZ5IqJcPOhh9gdFaYLQWGC1rXNnX5lcWmaxZnPlTWwRnsP4AACTsTNsyONawaZ+tsScv3MqYh+0GD0EFCMQDFiDA4QGWqrd4XnB0k3ljBcsyVs1bUjm9ByYAsCT13+XnXLL9tWt2v/VEzZnHs5Hu8kYiKjotPRHDsoZxQNEczCTrjIpxSEF2hgIAG0P181MJQu+wqso4LUfX2IME+ahK9BjgqR7vlXnJhnXO8mVm4gB9/vnnH3jgAb/fv3Tp0p/85CfZ2dnjX7rxxhu9Xu+n28NZ/hdwS8KwGBkQwkNipI8PDYrhASHcz4cHhHBAkXIM5mzOnGMw5xrMSx0Zl+aU5RkseQaznvpSb9QwwAd7msOv7y13N2emtxKWDrm8KqNopT61OIiFgDjCywFVjmBNJRBIogRdB13ut6incz6gltJnX7R6WcW0H8GQ1LPLzj59y8YfHdh6b9XqSa9pCopnZiSYNxVh+G3LyD1VkzgfPNHtXeIw2BkOAAwUyWtoinba68WieXog4NUd6jlLj4pA2OvlTfQXyWtmls8hRy00r7766qWXXmqxWPLy8h566KFnnnnmoYceuuSSS6KvyrLs8/k+i07O8nknoipdfDAsh8YkYViMjIj8qMT386FRiR8QwiMib6J16XpjFmfK4Iy5BkuVNeWs9MIszpTJGdP1s+VPJ2FnS/foUx8Vhtq5rL3hMrVw2dWO8jO6h7fvbn2+48Aer3ZjRF2uIL0GFAagAFGESENvdubH1fZGpvNd/eub333rjKIbri3MSpn6g/QU/eKKc5duelrBxnvnVevIiXrhgCBncQn6ZOlIotDENgSESutRXhUKwi0h8XBVXpKYylkBabhzv3jO9fbmXhQScE3ZUV5L744Eby2Z5h4T47XBwDmZyeZIm+ULwVGC8M4775w/f/6mTZscDsfQ0NDVV1992WWXBYPB66+//rPq3yyfOX5FGhV5tyx4JNEtC2MSH/3XLYluSRiV+BExQhBEKsNlcKYUlkvXG9P0hjlmxympuWl6YxZnStMb4o5a+hLjE6Q3Hn1r6f4OXForpQyUnHy7q+LMlo7XXn/5Ai//re7gXzREEYxkSdUK05VUh8ZQhNuPh0YJz0hBp7eswwdGpm79guesrc+G/lT/zvrvnHZ6zdSf6GD0G1ecu27zc36Z++fiORNCvjFOyrnn2nznzxoHfz3vKKXwiR7PFeOqLykI08cI4MN0N0v2VNrioB54R96wbOKFERWZ6ZkfXQ93ubMTFf+T4pbUE3rOOksyHPlhVFVtaGh4+OGHHQ4HAGRkZLz11lu33XbbDTfcIEnSzTff/Nl18rPh0W6PXUdtyLQdf4YexQv9vhKTvsoWXwTF5tHQIochgZmsYuyVtdSEppaCUECR/Irkk0XvuD/PkcfC4SeNtC6VNbhYzsVwLpZzsVy63lhpdblYzslw6XpDmt5ooOhPzWv0f5sdbT3S398tMQ/5S97MmHd+ztqHBCW88Y1rPd6UBu9rikrpMyPXnW6pdBwJ7eE1tZ8PYSAz9EaGpP/5vru1ofKlnuoM+8Z1zuccW3708sht531tw9SfO8/q+kXF8oe79v14v/k3VdkxjvlY0JFEvvEopVBBuDUkXVdwxEc0rGpTTIGWPWL5Eu5AN+IlvPRodXBMUtP0My9dXh8KMCSZ2LHopDza7ZE09I2iGdBc9/n4dE6Xof+SRo+cII6MIVEUVVUd7+9LkuSf//xnvV5/6623KoqSkjJj9odt27Y98sgjAHDNNdesXLny2AuGh4f/+Mc/9vX1rVu37rrrriM/C/fua/KdW93h79f3FRrZGwpdemqaPpybaXtpwP9wl3t9muWcTGuMK0mBib2vdZQm4Zp8VxYXx+DWMDze7fFI6kXZtiIT5VeksKqEVSWoSH5FCiiSTz70wK9IfvmTB4oUUCRJ06w6BgFtothikzFNzzkYvYPR5xnM1bbU6OPon5PVTxGE8OZQYFTEZ2cmVywbg6Ah4+wxD8B/3tq56MXawKJ+gv+w5IL7LXlLR90NL7/5dZr79Z6x5Zoh/O0rTVXO1OjFCkKPdjf+u6vhQGAskzORBDEohHMM5g0pef93U80zm8WOpgtfouadP/e+zObfv/IMc+5lp0/96TcXL/hPX6tJN/qTBuLueVnRARxUNCuTrL41QSmcoA4CgFtSU4+zsvtG1YBXzZ3D/uoZ+fwVE/OTvTEUOCNjhq2Xu72RjrD0nZLUGWlNxfj+ttEFNu7UtGTFqorx3zrGNIy/U5KWTDuDgnJ/28g1+c4Ka4KZ9gQN/b1z7IbClMROZ7sikqDhuZa4oyH7BTmLOyFhM0cEoclkSklJaWhouOCCC8Zf8dvf/pZl2dtuu2316snP0uOltrb2jDPOuOeee0iSPOuss95///1FixaNv0BRlLVr15500knnn3/+XXfdNTQ09NOf/nRGPjpeVrlMq1ymAwHhzoZBK0PdWpxq1R13UdCRxCU59kty7Fvd4TsbBkvN7GW5jmkTC+YZmJ9VZLhl+bGukdZw5LQ0c4GRiqhKVKr5FTGkKmFVDqtKUJEDihRS5bCqhFXZLx96fG+bxpA6M82k6fVmWmehGauOtTN6m461MWyOwWzTsTYda9WxNubQAxN9aNEZFpX/9Pr6ePmibNsKV9wRCGdmWPf6+F82DmkYNjiZpQlphCJC97eNRFS0xGE8K8My7YZjChoDQrFZz86gOvNpoWL86ONvr9veLazuZIT2Ode/wJjThkf3vfzm9Sb7Ex+1F1J5vj9dkH74y+nhgxd8/IqL5X5ZueKklJxo8APCuM4/9lBH3YJ3H79z7rKr5pQ9ubHo5dHbLyq9N2f/33aU5S9bWDZFHwiAP1evO3vLiy+uvPyuxqGfVWQAQFNQLDcnm1VuvFJ4rDoIAIOCMv84tXkbdwjli7naTo0kYWHJxNnXEZauzp+Y9PhgRPpvn+8bhSn2+EV4Z1h6eSDwq3mZ8b5xUsYk9e6moe+UphYYk00Z2BQUH+wYu7UkpSyJnwNheLTb3R2Rf1aRmbCH0auDgfdGgt8tTUughYiK/tY5hjD+dpz7DI+s/rV9zM5Q35qhDcoEjjqjvvLKK3ft2tXS0nKsBnbvvffecccdAJB8AP7VV1+dmpr6u9/9DgB+9KMf9ff3P/HEE+MveOGFF3784x83NzcTBLFjx44NGzb09/dPmgT10wyo7+Hlfx90qxh/qyT1sF1C0FRRUyOaImmaX5FETRM0NaBIEtKag+Fd3pCegmITpWJN1DS/IkqaFtGUkKJISA0qMq+pEtJ8ssiQlJHWmWidikiESRfL5BoMJlpnZ/QmWmeidSaaseoYi4410zoTzYx7iTFQNADs9fHP9/lMOvKbRSmTeqtPgYbxG0PBj93hIhN7ZZ6Di18UhVTtmY7hgzIUmtgrch2JqXeNAeH1oYBX1la6TKenW5j45dlWd3jzaEhC2EyTq1PMSxyG+DIcf0aImvbkg6+sbB8jV7apwtCcr/6DYk3+QNd/X76koPDh53eW4ALfgxdkUJ/ci1cWl7z31C3FC75XemgHKSnqlmcelwff0xEGqmBtzhlnX7rz9TPSCzaYFz7+AmQYnz4l9Bg5umbJvb+a4iguyiXbX1vtyqpxlG51h28vS4taOKZNfjYtCsJRpfDhLvdiu3HCCcKyTS33zc8+dismhNELD3gvuMXxq+eUr63XleceNa5UjO9uGo4KbAAQNPTaYGCvj8/idJfnOZxxzgIAcEvq3c1Dv5ufnfywwRh/POh51SPdOTcjSWsHBni0y+OW1e+VplJJdKzeL/zz4Ni1+a4YK14dS1tIfLBz7Ix06+nxG40Rhqd7vfv9/HfL0uKy68oI/7vL3R2Rv1+WlsBJUCIB9d/+9rc3btw4PDycmTlxQ/TDH/7QarXu27cv3n4cy44dO+67777o47Vr137rW9869oI1a9ZEq6HU1NSEw+GOjo6Kiul9wY8FA/hlEQD8ioQBgoqsYRRSZRXhiKbISBM0dUgQBQ35FTmkKCJS/bIqIFXWUEiVom8EAEGVNQAFKSpGv21VATBNIAlpeormKFpP0jqCNOpYCkiapGhCRxAkCRRJUMMi1PqAIckfzsmy6liWpKJijKUoq47lKFpPUjZGTwAMiXJYRYOCElTQNndkpzecpWf+sSg/xjtdZDcsshv2+vg7GwaDCroi33F6zKYYiiA2ZFo3ZFr3+4VfNw/TJD43w15tj2O2mGnqsiyL2WxuDop/bh+NqOiCbNuieFoAgAorV2HlEIZtnvCvm4cEDa9ymc5Itxzrx3g8oho8AERUtN0T/k3zcERFTpY+OdVcbTPEJVgf6/YQAE6WdjF0qp5OYXUnyEdf1LQn/vLSyh4/c8qQ6B0sv/zfpI5TNenVt29aWHXHw+8XR2zef52XMX4F/EnDx2dlFByWghhg+9239jo2iTZdFpqT2vzgYL3njR9dv+KjZ89ckp+Rz410f4Wo7iS37Pzwo7r1J1VP3Z/vli68bvfb3yqpVjH+c/uoR1Jzk5aC8IlSuM/HH6sOYoCWoDhnMkNZ406hsJLd0YFTrcQEKQgAW8fCK13G6IDZNBJSEL40x35JToLVEwUN3dU09Jt5WTOyeXqm1zsQEu6pykmyra6IdF/r6HUFzrjm4wR4Df25fdRMU3+uzklMlPoV7e+dYyxJ3FuVncAOddNI6LUh/9X5zrjCPTHA832+re7wt0tSi0zJqtRTc5QgrKmpqak5roPZTTfdNCMfOTw8fLiEU0pKytDQ0LEXHI5fJEnS6XQODQ1NKgh9Pl/dVZezTz6ASQIDBgIRNEmRhIo1DFjDKgDoSB3GQBM6AoAgKJogAUiKIEmCwphkSYoiKJYkGZKmCMInR+OZKJrUAegZksBIp6cIM00xBEkRVFAFGRFZHMMSFE1QmMAEJvQUoadII0WyJJgpkqMJC03qSWp/QPiYFwRVMzH0E10UQpqewhFN0lMkQqAC5kiSV3F058oShF1H6knKQhMywrKqOig2HA4fvtnNHv5PXV5BQRiAIgiSBA1jhIAAoCkCA6gaNtIkQRD9glyuJ1dOGb49LKvf3D8sHhO8pWEYENSdo+H/Lo6vOsFXdvcFNKApQkFYRvivHSPPLMxa7Uxk9i7Qw9O8dCAoPNfrIYCoP6kggUaWGcllRjMAeBXtx02Dr4yEf17muiHPFuPbz7Qzo7LqlpT+oFg3pnoVLaQihAEAmiMyADxVPQPWs7CqPfTIO+d0BbgNkr9jZ9FXHuYlDaTwzto/WMz52xrPAJBvOJ3RBP7wOOA19ame5vq1Xz08NhpbeoPcDo/p/910yVcJgtw75B15bZd+YOzm3MpHOw/835rlv+umO7yomBkN7WkIL54m1r6KtWgIbR3oqramjFLosQH//8ufGZ+Ri13s8i0HH1+YMX5UA0C3oJhpkpHFsHzU9YoELXuEVV/R//Et5eaztPCElwHubRyssjJv9XtWOQy35ZooggDQJjQeIwrG5+3sv6PEgUU+kfePQ8X4zhb3iKSebtdFEupMFAzwZH+gLSwvsDCPdQ6/zepuLUhExr85GnlvLPz9IqeE0Mau0W5e6ogoOoK4Z25MNkYM8OxAsCEkfafQkcJQMh/xqqhXkPslbVBQh0RlRNICKvpXVcakG8WOiPxUf6DKov9lsR0Ajf91EEAfr45IikdBHkV1S6pb1oIKCqr4/0qcfhW9OBQ6N910d4kdQAmHj8q3gDGSlbCiRDRNkpTIQDgYVoSQHA4IQUkRIoqgqmFF5lVVBBQpylp17ZpvTH2bn4E7r16vl+VDY1oURYNh4lrJcZyiHLntSa+JYrFY0t5++9prv8YSwGCggVi5aElGapqZ1pEEYdXFvYnwyqqJJpljLMMY4IV+//ujoZsKXTH6hTYFxTHN94ss+2W5jth3UG5JffCg20iRf1ycP+Gs6xS9/qQMh+H4esmgoPytcyyD091U6Jp231dogOdWmCxHt/bGcPCD0dC3i1Ny4lcC/j0/I81uVTF+qMvjkdTvl6Ymc9p3z4Lsh7u8CONvF6cmeeTHASxyCefnOi/IisOrwgAwaeJLBeHb9/f/bG6GIX7L23j2ePnXhgLCx3uubfcJV+V6d/xy7jX/Ya2pAOAPdLV3vXzuGe+8/hSllHhWZ+aMf+N+z1Cp2Z5rO7KzpikaA9Pmv5IXdCkuan4qsnznQgB4q3lEr9Nl280EiLxoJFmnMeQ+3lQaz4bMoo8CIysz8s7PN1S5bIaZ0AgBwADwwOKcJSkTD5L3e3xLHIZjO1a/l88pZXZ06xcU4eLsSfqwLt1yQ6FrimP72HlvNETT1M6Quj0YAACSAAIIAHAwlIulU1ndMqfBENt4/vGBwddGIwttXKpRz3BcwvrlTXt6XxwKlFtYltGtSrOdlGJKYMidvfVgnZ8vMDHfODBqZ6lsva7QxJxjtyy06w36mH7WtFcPpOlpF0NfWz8cfYYhSSdLpTB0ml5XZDWuNTBFRtZinKS1xZta/LKWy7E7A/JDfUGaJDBEoq8UAAAgAElEQVSAijAA6EiCxqKNEK2k4CQFCyFbIZJJSGZKDWmBP3wwZgDZRIhvtfHvYkmHRVKL6LBEIolBIQpJBFZVyqgSnEYwiDJqFEdSepLmCNqs13EMpbcZHUZHjl6nT+GshWnl097mkW9227Zt27Ztu/3226d9z0033XTXXXelpiZ4aJmTk9Pb2xt93Nvbe2zJi6ysrIaGhujjUCjk9/vHJ7gZD0VRGaOeuy+9MrGeHItrssHx3kjw5YHApTn2vy/Oi6WRPl5+pNuTxenursqMfRrwGvpH55hP1r5XlmabbG7rj+86y2vooYPukKrdUZ5hiXldsI0rLV3n5x/p8lySY//Dgpwp3jIFJobe7uWf6fXeUpxaHr8/2Hiag+IDHaO3lqTOSdpNI6hodzUNXZPvrEzUQW48GODnDQO3z8mYdJzEgldWN/b720JipZVL6es6p27opYvmr9n5/4ov+ANnP/TN7677W/W8az/cY2IJ6bKljgkH9jzSrDp2/JNVVUXqc3l2V9PPnyj72vn0I+5tKkkMiZHGoOeDtZc8+JEfgSEvS8R9XpGzx+KAvdyV+UzvIUeB4uR+ygmckjbJXuQjd2RNimVCx2QRN+0Sl15i2/im9surGXKy3dAPyjNmqmOnpVtPS5/YNwzgltToHyaIGH3XfzM/+zfzs8OK9sGA+97W0YSN8/+syf8Lwu8MB3d5I3V+MZ1jVrniHnVvriluCYkb+/2Chk5Pt6yK3yGu46zK5/p87WHp1DTz+jTL8e5A02RJDslyUJJDkhSU5KAkh/7oDOwdGxXCwUK9asQRWQ5JclCSgpIckuQgSdIsY2YYM8tYGMbEMhaa1utozqk3L3SYPaquyuma73QytF6nMzKMiaY5Hc2xrIWmOZqKVcmJnhFOe9kRQdja2vrKK6/EIgj/9a9/fe9730tYEF544YVPPPHEFVdcAQBPPvnkRRddFH3++eefX716dVpa2kUXXXT//fcPDw+np6c//fTTCxcuzM3NTeyzkmSXN/Jkj3e1y/SXhTGJB6+s/q1jTMX49rL02I+UEIaNA76dnsjNxSnxepdhgBf6fbs8kW/G/94oXln9a8eYk6HvW5Cd8FG8X9F+1+EpsJr+sjA3Gf0t6hfQJ8j3L8iJ/WjweLSGxH90un86NyMB78FJ+U3z8KU59gQ8R2SE3x4O7vFGGIq4Ks/59ULX83UtK14+YL75zMLdv0iZf5E1f1n0SkHwHOx+99rLt7ywHfUZgmtSJm4BszhTDx8c/4yOougL7tzw+jeft/7lkZfm0PQifSpf4yDOYs1/fVrjQ4ZU/Qs5EiEI2ezJ82LpbbHJ1hUJxHuPCfPucPDW4omhWQe28bll7Cu16OwaymL4bDyeCIAUlk5JKFTXSJPrXMYNJhMAeGV182j4lQG/hqHazl2UHauFkyUPHd4LGnpvJPSzhkGKJC7Jtse10Zxj1v9feXp0BP68cdBEU9fkO2MM7UdI1an+C+3+COfbPTT4q4ZRAw4tMKqg+AXRJ0o+UfQLol+U/BipDGthGTPLmFnW+omEMy9zmmldWlNE1yjSZamu9VmZHGthGTPDWijyuA4sJwMAwFZ3+F/9/gIj8/VcVwIefHFx1NfR1NR03nnnTfsehKbKCjgtN9988/PPP19TU0MQhKIot9xyS/T5a6655sUXXzz11FMrKyuvvfbaJUuWVFZW7t279/nnn0/m4xLmw7HQkKD8cUFOjAtynZ9/dTBwc3FKXO5qDQHh313ur+U5L455ehwmKqcvz3VcPD+RwwOE4T993qaAeFtpajI5L57v9+30RG7JteU7Yz2Bm5TuiPyH1pFrC5yHM28lw2uDgQMB4Xfzs5JxtBvPI12eRXZDYj4L9X4+XU//ovLQseLeMU/GI1uYcxa1C3uc0mjO2iP+Yu1db+bnrqNpq1cUqLnKsZ2fY3EImtoc9JZbjlhHFy2Zt5996LL//LzZTtah25XB3NFBZgwwRXjmpzxUJe4O7x4aNV5/zrqFsfTWTDNhdZpaEDNFY0DQMJ6gr/Mh1LxHKDzd6qtD66u/8NlYHAx9YbbtwmwbAMgoEa97jiKjEjGgaC8N+B/r9lycbY/L+ZP5RKZ2R+R/HXQHFe3UNK7GJAuCNyKMCoJXEL284OZ5tyB6ecHLC2Oi5FcUgdPb9KxNr7fpWXuN3iaTlj1BnUxmLM9YPN+RfuglvU1HT9WZJQAAsNUd/vNgwMXS1xfauBhSTUV939rD0v1tozQB1xe6EvAEjpEj4ROvv/763XffHePbnn322ZycBG1oAKBp2u7duwFgyZIlh+vd9/X1paSk6PWHNjttbW0DAwPV1dU223GX1/+BeoQaxgmv1N0ROc+YeHhpQ0AAgCRthv/oHKu0citdpiQzyzzS5RkWle+XpSXgkzYBDPC3jrF0PR371nta3hgKeGT1qrwZkNBeWd54z7OrTZbiW07e+ufTKi570JV9pFL8K299vazkPJP17F8/Jiprxv65ZBJr/F1NOzrD/sdqzpjwvKyoH774JnfgZRa3h/ReIEUW6VnJRYhzBhZdeNalp0wbOxGlzj929a636k+7KpnbjJFfNA4FFO2+BUcpvltfCZEsubGXvvFMXWn2FzLTwuehHqEoBSL8aIQfjURGIvxoODLC82NhfoQX3LzglhVezzqMBqeRc3Gc08A5Ob3DaEjlOAend3Kcg9M7WGbyGS1o6D+9PpqEBGbEwYj0eLfHqqO+WxpHWoARUXmk2yOo6BtFKZnxJB6JMXxitjDvLDNDkoLwYEQqTDroOMoP9w9cleeYkUPBKHu8/BZ3KK55ezwwwK+efPPy3YOF917Vu/WPO4eGLr3q/vEX/OOxRVdc/HrPsOufL0qw3vun6km2myFVnvf24w8uWn9m+iT+tOFwWEZER3t/OBChaNqV5SwvzIyrDP2zfa3/7Wt7YcU0WdmSBwOUvdHw1LKCJY4jidc9Q+rbT/m1BVYVwbWnfVETiX06ghBjFOHHwpHBUHg4HBkKhQfD4eFQZCgq+SiaNRnSDIYUkzHdaEgxGtKMhhSTMZ3TOwycU6+fsW3ipwavIV5FcZmvZgvzzvJFYqakIADcO1nRn4TpDEsbB3wTckYnzMN1TVdu7Um//TxF9g7vez505uPjX5WkoKqJJmM6SaoAEFQmP+Q308xTS8+6aPsrb6++aL5tksSHDouxZtFUSWSm5p2RnjUpM/kdHo+PxkIMSY6XgoBh+5uhjMXGV9vQL782kzmvv9BoSAmFBoLhgWCo/9BfsC8YHuD5Mb3ebjZlmoxpZlOm2ZSZljLPZMo0GdKMhlSanklHp88DBoqM0Xc3XiYXhK+++qooipO+dLgq0yyzfBmQEb6rcmYSbrWEQvb/7GDWVXLFGV1v3TVauGF9QeH4C3jBbeBSAMBhpRQgOoPS8Zpa6cp8oHr96VteeG75htWumRRaY5Lw0kDH3ZWTZACeKeobH59f8TUAeKBj7Kbio6JU2upERSPe6yYvP4k2zmhV5C8KkhzyB7oDwR5/sCcQ6PEHewLBXl5wmwxpFku2xZxjMWXlZq+ymrPNpmyTMY0kZ5WZGWDyL/GGG24YGRmZ9KUvtCl1llniJclQkMOoGD/27KYbMZ118QqF97obXq1f98iGo6OvNKRQFAMAKTZCIQn/MBY0dDx/uYuyS6w69pLtr36vdNH3SxfPlE/Q7fUfXp1fcbwikbzgVlXRYp48nClGeN4NAAcj0ubR0L/HHYKKEbRnU1iZa8nBxOLSuB19e/q35GXPTD7kTweMtUCw1+Nr9/m7fIGDPn+Xz9+hqKLNmmez5FkteempC8pKzrNZ8symDIKYLWR2AplcEO7cuXN87AXP8x9++OE999zzpz/96dPq2Cyz/E/xQF3TjXuGc+64EChydN9zjjmnLc2eGBSk0xkUJQIAJAmpBlgl2d8YCkzh8nNKWu6u9Vdcu/vt5/ra/lS9boUzWc319617av2jO06+7Div4517/7Jy6Q+S+QhVFSmaBYB7moe/UZQyvvrStjdCxmLuowH8i6viPhr0B7q8vo7PsyDEGAWCvWOeZo+vzett9/g7/IEuoyHVYSty2IrTUqrmFJ9vtxWYjOmfdU+/jEwuCPPyJvqqVVZW2u32H/zgB+edd95hP89ZZpklFtpCYcPLe7gVZXR+KgAe3fff0ov+VHRMMlijIZUX3AipJEkvLqV21Bv/1jE4te9rrsH83tqLn+5tvnzHG3MtztvLFi0xxJHO8TCipt5xYOtbw13vrb3YSE8uhw40PTOn5HxGN7myGCMjY/vTUqo6wtKLA/7WM4/kTexqlEZGtb2M/rrTdKb4jaJ1DY+tWf6TZDp2LA0tz2Zn1NisiWT4AwBFiQwMNY15msbcTWOeZq+vw2BwuRxlTkdZUcGpi23fdNiK/veO8b6gxGFfPvnkk6+44orm5ubKysoT16HPDweanynIPclkjDV7RU/fh1kZS+Md2cFQf5KGplk+52CA+97e9lO3nPbDlQAQ6qsldZwxY5JJRFOs2ZTp9bW7nOWnLde9VY90/dQHo6F1qVO54xIAV+SWX5Jd+nhP03fqNkuqclV+xYXZJRWWmFzbJaT9p7f1l807FtlTd6y/3HacxIT+YI8khzLSpsnZPS3Do3WV5Zddvqf/+2Vph8ukRIJo25uhwWxzTSZVkRe3N0RL+0vFBWfM7GlZQ/N/OM4RlxRUlMjI2IHo3+jYgVBkOMVZluKcm5Y6vyj/9FF3w7LF30m+Y7ISoUhd1IQ+y0wRx9Bpbm4GAI6bMa/0zzllxec2t20Mh4fmlJzvdJROe73Vkrtr318ZnalizqWcPtZd+cjYgbqGx7Iyagrz1hPHL4F7LOHIUO3+hx324jnF5yWwr5Tl8N76fxYXnJHimhvvew8zOLw3xTlHl5yK8D/Pk92912zvc162muAYAPA0veWqOPt4F2dnLusd2OZylhs5YkkB4exJ/dbevj2nzZk2cStDUl8vmPf1gnkf9B982d27YetLCkJrUrIW29Mqra4CozVdb4zWocQAoyLfywf3B9ybx/reHOpaZE97aPGpJ6UcNzIYIbW2/l8nrfx5gl/BOCQ59KEX1/mEp5YekjEYweaNAT6bUYC4aFXcwkyWw15fx5yS85Pv22HqGh61WwvzctZMfRnGyOvrGBqpHRzZOzxaHwz1pzjL01KqCnJPqll4K6tLM5utANA3sL27b/OMSMGu3g/6B3csW/TtZAShqor7Djwyp+Q8sylhWzpu63yjtOgsgEROpkUpAID1bNz5N6LGkgQ+cVomjyOc4DUqSVJ7e/vf//53k8nU3t7+mdSLn5RPIY5QQ0pbx2tub3NR/mmZ6YunvV4QPA0tz/KCp2ruFXZb4bTXRxkZO9DVs4nTO+bOuXjqHA0T8Ae6mtteRFirmntFvMNaQ0pn1zuj7gNWS155yfk0HfcWx+c/2Nb5mqqKeTlrrOa5ZnMiZQr8ga6mto3ZGUuzM5f977nABRTlB/988RcjWvovLosuGvv+ur7s0gcNqZNvrbp6P9hV+5evnL8RAAQJbn9Q0NuD4jzpgYWxZhkMh8PR8LX2sO9j9+Be30hz0NsVCQyLEV5To9eksFyOwVxpca10ZZ6dUZjFTRPutnvf3wrzTollOzgd+P2df77Bvf6BRblnfFLTbvMrHY3duIVOuesqq90c98K6bffvqyuv5bgZyHUQpa7hMYetKDd71aSvakgZGa3vH9o5OLR7cHiPgUvJSKtOT6vOSFvocpQdHsCfxBEa9x14lNEZK+ZcmmSvJDlUW/+vFFdFccHpybTTO/Bxd+/mBZXXWMwJOhuPjO1vbttYVnxuRlpMiYrGg9D/Z++8A9uqzoZ/7taW9957O3uRHUJYIawwQqDMMtpSWjrejq8F+rZ9S0tpoYUyywgjjARISEISErKn956SZcuyJGuvu8/3h4LJsGPdK4eGot9fiXzPc4/GPc85z+RbOt4OBkdn1N43Ubb+uPA83dy+QRT5WdOkNUGKKqE+LS3trKhRgiAuvfTSv/71r2VlZZLmcUH52hLqIRQNpj1Dw8eyMuYW5K6YdB8kCGx336d2R1txwZWR/1w8XlNb1/sQirWV6yM3yQIAWNbf3v2hy91fmLdyogf4PLjc/T2G7SzrLy+5PjF+kjY95wKhOGg+3Gfcp1Rqyouv0+skF4aFUBi21g9bTrKsLz6+sCj/chmOKEFg65tfSUwoTkmqungiDn5a1/Tga8dzHr4aL04HANCuwbbXb535yMGJrhdF/tW3F625/JXwSf1YC//GTrY7c/iG2foHCsdJGTyXMUU4VYQNfdUV66IX5XL3f6/eRGryXpuTF36mOhrM5p6VbZqE711DlmRK3mFb7S2jjo7o1cwYJxqeT0+dnpUx7/QXRZEfsTUOmo8MDh+22pri44sy02Znps/JSJulmkABQwgdjsHWrlerym9JSoh2zTSY9pqGDs6d8f1osuD9AWtLx9tpybX5ucvlSQgEbc3tb2nV6ZVlN0kyX4UxDR3sH/i8qvxmSR8IhGKvYceIram6Yl2cLqK2B6cTlSIcGBg4PWqUJMn09PSLMEbmAilCj3cQAEAzTo4LcUKIDrkBAIGAFQBgd3Y4Xb0Z6bOXTWwm8gftAk8HgjZBoHuNu9weY2pK7YJZP4rw7jTjrGt6JRC0F+atLMxbGfm0wyuL2XIiTp9XWriaJKWthrzA9PRtG3V2pCbXFuWvkno48/l8JAl7+re5vUa9NqeseI08k6nD2d0/8DnDevTanML8VRMtNOMiirzL3W8dbfF4TYLAAAAS4otTk6oTE4rl2XCipMPre/3FLT/FdYmPXB1+xd78kbt3X/H1T59nVH3zy2bLidWrXgj/99UtTFsPvzt74Odz09blTG5yn0gRiiIfop0UqZV09Of50P6jf1i+8Ikp+QCfOb7tr9aMEysKzf2bXO6+zIS1R7alt+k1q+cTi6okLy8Qil8cenzpJb+VsSiPK+/oyb/n5SxJSznlB3V7DMbB/QOD+82WY3pdbnbmguzMBZnpcyLZpQ2aj3T37Vy84KeSDDznwjDe+pZXUpIqC/Muky1EFPmWjncCAevs6Q/KeypPSQjaZtXeL3VhAQA4XD1tHRuzsy7Jz1kmaaBp6GCv4bOy4msz0mZKvWmYb0uJtb88fcejj/6AZl2CwPN8iOOCEIg07QEAcFwAxQgAgChwBKFiWC9JankuhKI4QJAzXuRDKIIjCOoLjiAiFCCHoAQUOICiUBAAgABBUBRHAMLzDCeEtOp0itQiCAoBBAAgAIFQRFBMFHkMJVEUpygNihC8wLi9pmDQrlIlJcWXhGiXILIIQHiBwTEKQlEQORxXiCIPoYBhlCCwCEAwjIQICPhGUpKrLl/xt7E36/EYuvs+DdKuEO1kGB/L+U49/xCKUAAAIAiKICgv0G6Pcfa0B2fWfvc8Hx3L+ptaX/MFbCHaHgq5xl6HEDrdvRnps1df9i9J38XRE8/7g0aPdwhCIcQ4fb7h79z6hVo5blO/yeno3tzZ+/HoaLtel3vTte/LEyKInMPZZbW3mC1HB81Hr7j071np8yYfNgG8wHi9gx7f4PDIcRTg8+c8OumQG/cefOb99tRf3YhlnlJgxs/+l9Jnps+7a+waq7UhxPryTnNH8Tz9+sYVly39S3bmfAAAhODPb9GjNn5Hjumh6cnnPxeGWE99/StqTSLNuAEAosgDAFAEgwCiCKZUJuTnLJdkQt+x55H8nOVKRQLLBUSRZ1gvhCLDeEXICwKTmTZnUkfaGN0+eu6Our9mdlZQwYrSGzAx7aNX3J061bQy/PpL5JjEDx77U2baHK023R8YCYYcwaCd5fwoSogijyBoanJ1Qe6lEQuDu/f/ojDv8uzM+UPmI/2mz42mL0SRz81enJu1KDtzQeRefwBgQ8u/PV5zfs5VudmSjYen0z+w2zR0aEbNvW6PEUWxs86pEWK2HO/u21pTeXvY2OPxDjg9/QJPF+VfEaEE09DBgaED5x7IgvSozzfiD47QtKOydC0A42xH/AFrU9sbalVKbeX686RC0qyXoV0+v4VmXCHaW5i/IhRydfV+kpRQVlI4oUN9XFjWH6Jd4WOMP2jjuVBifEV62iR9V/4bXDJqdbJanapQxhGYEsMolTIJAKDXZY77xZyf3r5POT4EEEyrSQcoqlWlIyiu06QDAExDB/uMO0sKr8pMnxuJKH/AcuTE08mJ5fnTHlCpkpXKJIrQajST1Kvk+GBb53sM65u+8q5zd14KZXJCYplGlaxUpoRndcZYLtDc/pYo8tNr7omkX5dSmZiSVK3TZ8Xr88Of1dDw0Z7+7csX/U6GN4iidFnZN6QkVAwM7bdY6+fM+L4MZ/gYCkqfm70oLaV2zozvyxaCoURKUlVKUpXfb4uvKJKkBYeGj7o9Rn/QCr7cKWIYpdNl6bXZNOOpqZi8BeYuq21m3ZC2Nm9MCwIAgvaeuOKlZ9xo5KTF1piVPnvsoIbjimULn9i97+fr124nCDWCgEfXKZ58k15lynkbWLp89J9rsybqc0mghNXetKTkV1N1CE5LrlEqEghCRVF6itQgCEZRegRBJTl4AAAOll99sO97yYO3zb6FJNRMSNzyurtXr8zLxK6TpQUBAKOODrUyVRBZlTIxXl+gViXL8HOHOV73bK9h56D5iM8/HKfPL8hZvnrVi8mJkzd0PZetux4cGj6emliVk8HKm0yYD7eudzg69frcXV/8TKfPKcqXcyLc8MGVDOvVaTI/3/9LBCAIilGkXq1KSU2JKPLf6ze/s2mNWpGkUMSN2BrBmacmglApqDilMlE7gSfi/U9uZhifSpUoCGyf4TNR5CEQUZRAACKILAJQFMVFKEAoELiaIjQ4paYILScwHV3vkZQ2TldgGNjTZ/yMpj2CyEIoQihiGMlzIYJU81wIxYjwMeDUi4SK52mCUOO4ksAVCoUOQQhVZHvxb/yJ8GvwEY46uzq6N6Um10S4N6EZT1PrGyLkZ9Z+N3JfF4RiZ8/HVnvTjJr7pPqxw2NHnR0zau5TqyLyJJ2FP2Btan09Ib6ovOR6GcMBAD6fTwTuuqYXi/OvDB9lZMOy/qN1f8/JuiQve2k0csI0t29QUPFS95UjtkaNOk2jTj1LnQSC9taOd+fO/MFEA8OIEC7a/vmmrYbk365FU7/aENQ/u7xi/WuK+K/cqIdP/GVa1Z11TS8umvfL0yXs3v8Llg1ceekzpwSK4B/v071mMZDj6EoIvjUvf6K2iG63vaH1Hwvn/uziieYN8OLKfd1LU7Thkq0sDbe94W5GqcRU4sGriP9g7F0gaO81bO/p326zt+RkLSrMuywzfU4wZHe6er2+IQgghCKOK+L1BcUFl0e+seAFxjx83DR0DEF5vTYnP3e5PKe1w9ltMO0J0a7M9Nl52UtlhJLxAtNv3B1NQJzZUmcw7SYIVW3FeqkeysbWN0dsjYmJpdMr74g8sn3YcvJY4z8JTFlcsEqtStVqMjFcoZG1rIFvj2n0gipCr8/c0b1JrUquLFsbSYkjQeQ6uzd7vKZp1XdGuBMJYxo6aDR9UV5yvYxkhkHzkT7jzsrStfISIb60/ltnT5PpPwgLOdHwKgDMrGn3R5nhZLE29PRvmzP9oamojg+P1f0jLaU2cvPdpBw69uSs6Q9Oeh7aMDA4+tGx+xR69f1neHmP/bF69k9PoF8uChAKR+uemT/rRxZrg93RdvpBkxeY9z5eW5i78nSlu2kPs6tRzE4IPasffKI2896CpHPXZr/fj+HssbpnF8//1cUQhevnxasO9JRpFf+alYsAwITgtjc9zYBMTCMevJq4wP1Wx4emXd3927p6Pxl1dObnLivOvyI3e8lEK7Ugch6vKSGuUNItxrpPeLwm09BBj8+EYVRm2mwZodEQisPWukHzYYFn8nKXZabNljQ8jNPd12vYwbGBkqLVMk66gaC9q/eTUMghY7jbY+zo3iSKfE3l+sjN8izr7+jZ7A+MlBZdk5Qgv4J8TBFGS6/hs0DAWlV+S4Qr+9DwUYNpb03FbZLCJp3uvpb2t3KzF8s4/bg9xua2DclJFeUl18mzgw2aD/cZd9ZU3i71OT8du6Ojvev9/Jxrck7rqycDUeTrm18mcFVt1R3RyAkjiNyho3+St7eYCLujw2pvriq7+fyXsaJY++nO/Z8NJfzi+tPtoiLPnHhy5txfto69MmJrDEdFAQBaOt6J1+ef7gcKBO3vfXTDjJp7T/9A2g38vz7h4iDflGt36Ll/zMieFndGOEY4WMbjNTW1vbF4/q/+I1FCY4wy/NUHe2v1yudn5qIICPrErRvczagyJxu/5/KvWwuGj0edPZuHho/m5SwrLVqdl730AmWmn9uGieODg+bDFKWXp8nAV8e7VgUVV11+K0VJzlYSBLbPuCt8QCwrXiM1kGcs4SoxvqS06BpJGp1hfZ09H3k8A8WFV0VelkEQua7eTywj9fm5yyIJ1z+XmCL8uoFQlBG9FgjaVcoEeRV1TeZDmWmzZT/JZssxhvVJCSgYh/rmVwhCVVV2s98fiKYfoddnbmh5paZifeTJl+eB4wIHjv3fjJp7ZcRbn4cvDj0eyTHrub5+Zk/rfSFc8/CVp78uML66vy+d87Ovfq4nG/9VXXHb2Pny0LEna6tuPz1zxusb+uCTW6ZV3zmj5t6xF0MseGkz3WmGeQn0v3TmJVmax6oyxiylY1GjVnvzoPmw1LyrKaTDS19zsPem7Pj/rc5EAHBa+U/e8bYplDPK8FuWEFNUJDwiLNaG9q73u/s+TU2pKS++rih/1YW2G1/QfoQ048ZQIpq34HB29xl3zpnxPXn7JKutqcewIytjrtTtuyjy3X1bbaOtudlLpBSGhUbTPpP5UGpyVXHBVZIUcEwRxvg6gFAIa/EoG/O2dm6sKLlhSkx5gaD96JRIBiAAACAASURBVMm/LZj94ylMsgYA9Bk+w3HlpFbWkCCUbt918gtrwv2XhXMHxxDYYN3TC+b8vHHslcMn/rJg9k/G/ssLzIEjv188/9enb258/uHNn96Rl7100fxfnL5hauvj/72Dg4wYnxF8lhy+Nifup2VpRRrq9PQJo+kLr38oktCeKecdk/ORhsE/12bdkZcIADC0MVu3B3uUyjWXECumfU2JWCHa2d79YVvHRhEKFaU3VpTc8LUlmF4MHeovZgJBm1qVInWUbbRNo06V5HWKUBFeLDViYnxDmaruMFVlN0+VQ8tirV+y4NdTqwUFkTOPnIjE1/hcX/93fYhSpzpLCwIAMEIh8gyAYvi/vMCcFbyAY9SsaQ8cq3/29Be1moybrv3Q7mj/aPvd4aSIMJWF+JMPKlfMJS1Wzd3Gwux+1ZJdXTcc7jvgCI5dk5ezlCK1vYbPpL7faBhl+HVHDb9rt+xcUnJHXqLAwUNbfe/uYvs0qoeuIb8eLTg0fHTb7of//c6SUUfniiV/vPOWvXOmf+/iKbMQQ4YWBACkJFVK0oKR85/3pceIMbVEWYNqXJrbNlSXT15aJcALf+nqre8PUCtrx/kzguLKOC7oJNRJAACz5XhG6tlpwlpNRmb6HINp7+mpxwpKf91Vbxw6/uRbH1x5+fK/ZabPCb+OouDKS4hL5xJbD7C7m/D1gjKFZn5ttz7aYb8nP+m23IQ0BVFatKa1c6M8u71UeAhf6h99vM1ye27CK7PLlRhqNXE7Pva3o4rkLOzxKwi9+sLaQ1ku0NH1YVP7mwDCmsr1Kxb9rwxHWoxvITFFGCPG5FCkNhLn5fN9/TfjGpVthJw9fvARpc+kXYNhRWgZqZs9/aFzrxnXd4Ki+KJ5v8zKmL9t9/dLi9YsmP3oWJQjiYPrl5GrF4Hdx7mdddglbF6enh8UvZXtbTMT1Guz46/Nv+FCa0FWhG+bnH9ot+SqqV1Liqv1ypBf3Lvbf6hfHCGVNy4iltRgF1QHutz9ja2vdfZ8nJO1cPnC38nLPY/xrSWmCGPEmJyK0hsnvSYoCE919x63k+TiCoCPbwBUJhcFbT3arOkAAK0mQ2qgU37OsvVrd+w9+Ns331+1fNH/nq4yCRxcsYC4fAFxrDmwt4EMdSU9BOJSaf4o6/5Z01C5TnFlun5lqm5mgmqiZHx59PmZ142OVwyjlTrli7Nyl6ZomZB4ck9gTz0/SFGVJdj3l+JxmvPdMcBzE3VAjABoHNzX0Pxvu6OtqvyW22/aSSmT/5OZiTG+mcQUYYwYU8OL/YalcXHaz9qoxyfMr9Bm1vjNjakzbgIAyCsVrVQkXHnpswbT3s/3/zI5sWLx/F+dnq6DAFBVAOfVKLxBuPs4erQdJyypj2CJKanCMBK8f3DAGGTnJ6rnJ2lmxatmxKvSFHI0ECvCE87ALqt367BnKMTdkh2/c3FxpV7pGRUOfOo/1CEOk0R2juLHi4n8tEl00sbBLgQgN2VLrmTE86H27g8bml/FceX0mruvufwlDCNfNrQUqtllKRP2k5KKn+c08pV0jG8MMUU4PiKEnwz3rc4oxCLePnf5XKVayTngnCjGNrD/BTCi+Jeu3r3KVDw/FU2cMHpWlzvXfPil6G+Xn7Ms++bd9c0vv7NpTVnxtXNnfP+s4CCdCrl+KXn9UmB1wv31bH0fdA5Tq0RddjxUEYIJDf7NZqt3BxEEVOgURRpFnprMUZEpFJ5E4XoCw9GvfvZ+TnSyvIXmBoJsj49p9gQ7vHS5TrE8RffUtKyFSRraB40dzGtNnj4/OooRlUXoj+bhk6pAAMAmc4+PZ+/Nn6QO5FmEqyC1dL6bmTbr0iV/HCt5uGGgQ4dTU6gFX+xv1uLkrTlT02/nwKh5UZLMzkcxLjQxRTg+KILkqnVPtB9JoVR35VepsMk/qAa37WVDy4qUnFVpeREqTwHC/+04SqDYnXkVWUppuQf1LttHw73rcsrKtJGXA/6KPr+7wW1bk1EUjRqmBV4RwSfzbeDfhoHpcfq0QwPk8vNVcVQmFSIIGrB2qlOjXV5xjJoz/XtVZbccr//HaxtXVJffMqPmvnObdaQmIGsvpdZeCrxB2NAlNHTyjf04J1DTBd0VapiShFCQdwPeRHN7/D47w9sZzsMKwmlJVWocjSexDCWZrSTmJarvLUiq0Sl5Dxy1cIYj3HMD3hEGdRFEnEaxaBG2oAKLMCLm4+G+USb03YKayN+y1d7S0PKKYWBvecl1t1y3+fQk0U3mHhxFZZwsx4WH4u87ji1OypoStRoU+Ke762r0MouEnc5A0PtsT8NvKubrCPl1ACAA7w12rUzNTSAlN/Qeo9UzWqWXGcDJiSKGIOjXmUk6GbE8wknoD3jeNnWSKHpPfnViBL+bg6PmzebePLXuvvzqCJWEl2PfGGjv9DlvyymfnyihDSEjChsHu447R5YkZ12XWYRLDIioc1k/Hu4jUezW7NJCjZwC2X/rqbfSwTkJaVem57OBoLw8wnavQ40TuapvcHQfD2HJ9p0bSyuLn94R97e7JnIQhjHteQpCMXfFT6dwAv6A5XjDc109n5QVrykrWpeeNomWdXhhh1HoNAgmG7QFIAKBUhCVQNRRIE6FaJVAo0KUFKL4crEVBRiigS8oegPQHUDctOjH0CCKkQSan4LUluC1+WiSXsK69tmIscvnerg4ogojEAp9xt31za/4/EPTqu6sKr/1rBJ3H5l7nSx9d35EhaQnxcHST7QfeaR4Rr5aL1vIWB7hcefImwPtvyyfm66IKoVfhPA1Y5sh4PmfsjlRuFRBl8/1sqFlTUbhQrnH0/6A57nexgVJGddnSu9dCsAHQ93HnSO/Kp8bR0zeGGAMAcINAx1BgXuwcLx47ImJJdRPJTYm+IaxPSBwd+VV5agmX+57/K73B7sxBL2voDrCbZcI4acWwy7rwKyE1HU5ZZK0Wp3LumW4X0eQ38mrjERbn46PZzcOdvX43LMSUq+VdUBs8zq2DPeN+L1XZ5esSM2Rus0boQMfD/eZgj4CQRcmZS5KzqTQi67z5fl5yzT4cr9xe0At2r2qO5ee/2LaYWx947YZD+9Fp7q4VyBob2z5d3PHO1npc6ZV3ZmdOS/CuiFuPxxxQbNVtDpEh0f00iBIA0aA/Fc9SRECh0oCEXHWg3viEsTVxelFqUSC9IbyAIBd1oE2r+OR4slbFDGMt7VzY1Pr62p16vTqu8dtk7nTOmAKeqXaVyei1TP6r/7m31ddopeyTJ8LhNDj970x0keg6AOFtVGefVo8o8/3Nd2bXz0jXk76XZgAz71kaKFQ7L6Caqmb5jEJz/U1CVB8pHiGDFPQCefIO4NdazIKlyRnSRq422raMWJYl1Mu4+3HFOHUIAIw4PcAAMyhgE9kPzD12NnAXXlV12UWTTp2OOR/uqeeFYS12SWR77/CWk1LkPfkV0naNFnowHuDXSN08NacUhl2mDqX9ZPhPgLF1uWUFUjfC7u93pMh9177IALAjVkl0+IkT0CAsNFt+9xmcrJ0AqlYnV5YrpNg9e3yud4xdSowLFulzVXpclS6DKVa3gMvCQjAtJ17nqypnP/Pvar1i/HSycsKd7xzb2LZqpTpay/EfNxuu2l4Z2Pr61DkqyvWlZdcL6WX3gQyOWbDQEe3z3VNRqGMvc7pHBg117msk2pB+2h7U9sbPf3b8nOXT6+6KzVl/HPAbqupzTv6wwh0aiRsHzEccVgeq5gfvdWu3+/+a8eJh8tmlUiPGzidkMD/o7cRR5CHi2dEHq9wFhCAtwY6mj32R0tmpSrkNAoWIXzb1Nnssf+oZKaMo60p6HuhvzlPpbsnv0rSZ3vSZX3d2LY4OWttlkyj97dFEd79ox9+tO3TwZAPAmCjg4woeHnGz/EhgffwjAhFBxsCADhZBkLg4xkCxUUIIRAJFA8JvAYnvBwTTyjcHKPGCT/HAASlRY4XAYSQFgQCQVnIUxjGiDwOcA/PhAQ+jVKmK7UognAir8RwP89rCTLAcxSK8lBEAIohgBFFEkH8PD/CBio0iTdklbhY2sYE/DzrF3gnQ/sFjkQxXhQFKJAoBgBgRQFDMBxFgzxnCLhXpORumPtV80xWFPsDnsGQZyQUsoQCI0zAwYZcLOPhaAAAAlAEgQAAWhA6vI5XZq26IWsSw0Wnz9XjcxoCXlPQOxj02dggAICHsNUzem9B1Z+rl0j6Lpqt5lba1+Kxt/kc7R5HQOAtq++X+H1+xUmX9amuk0edlkWJWW/MvTzygSGBHwh6B4O+waDPHPKzooAiSIgX9tgHtl5ybZpyCkpeHXFYbHRoTeaptMJtlpFft3acqJrm/9NH+qfvBBE8577But6PfzbtwR0IRhxzWDJVGqke4omws6HjFlOaLs7NMf7RZlv/x0HrYSyhBk1fxsdPC0FkfW55ppQPYb/dvGPEoCeoO/IqojTuAQD22YZOuq2PlkzYbZznQ119W1va3w4ErdXl66rKbz3X63m6tAaPLZKTZSQ839+sxog7cuX0IDyLt02dfX73/RmlKXFRacH99qFPhvseLp6Ro9KyokjKcuc3ue0vG1puzSlbkPjVFo0WeUXEhZyOOS1vmzpvyS6byHET5HkVPr40F0v/s68JR5DID5F+ntXgpCnoe93Ylq5U35VXJXsHAACgeZ4TOC01Sf+pb7wiXLn19auuuBwAEE8qcQTV45QSw9UErscpCsVSFCoAQI5SCwDIVGkn/SX9rGX/cCiAI2gCqVBgeBxO6UlSjREplGqY9h8ZNc9ISLs/Mve+k6XvPbFzIOibFp+sJ6g0Sq0nyThCkaZQpSrUCQSVMt7WjBPFNwfa+wOeh4unp1BnXPC5zfSSoTWJVCSRihSFKkOhTldoctTadIVmbOzLhhYLHfhJyaxJfekW2v9IwxfpSnWeWpen0hVpEkq08R1ex0uGlttzy+cmSHBVhll/eGuOLr5an0iLYp1z5JdlczKi0Dq/bj3k4EKiAJ6evjSSSKXz84uWgxba/9psCQp1XJo99ndMXccdI98tqLr5y2DCxXv3P1RUcG3DiOgNqdZHWke4893v6gsuSZ/znX/2Nmwe7rs6veC7BTXRv9MTrpE7jux4ZuYyBCA6gsQQRAE5++Dnw8atbmdXXu6l5YVX52QtjDB/UQBg/udvPVw047bc8ikJbFix74OxyMkUhapArc9X6/PUOgpFh0fq2rs+6OnfnpE2q7piXX7O0kmr9+Vve3ldbhkOUB1B5al0eWpdrkqXNNmSNy4P1O3+cKj3lxWz1+dUJMuSMMa8z98xh3x5av29WeXfKZYQCnQW03e96eGYTKUGR1FeFK9Iy/9leUQtwU+n6rPXWVHIVGogQCAQx14v0ya8MHPleQaGOeGy3XvyMy1GaQkiIHAAABR8FeQiQAECBACgx8nNC67Bz1xdBQDWH9lmZ4Ml2ngRigGBc7JMUOBQgDCiSKIYAmD4HwAAVhQoFIUAYUUBRUASpdRh5JKULCdLCyIYYQLhIw0vQg/HslBkRQFHUBFCAACKIDwUSRSjBV6FYeFjiZdjdQTp41g9Tt6TW3Fj7iRe82+8IvwafIQDQe+bAx1pClWEexNWFF4xtBoD3kdLZ56lzM7Pbqtpq6X/3vwqGeFYu62mXdaB7xZUywt78XDM0931yZTygcJaefsvn88nKsinuutq9cmTHkbPDwTgmZ56LU5OSfhDs8f+4VDP45ULohFycNT84VBPgUZ/X37133rqv1c0TYuTAIBjTtetR493X3FZ8LH3VbdegpdFagAPjfa3vb6u5v4tI6hil3VgZWrui/3N8aTie4W1UQbi7h3q72R858YU+APWnv5tPf3bR50duVmL8nNX5GUvPc95a4wTzpENpo7bcsrnJExlrU4bE+z3e3osDdbB3Yj1AEDJjPyrV8+4W6NOlSrKy7HGoMcY8BoD3lE2FH5xdXrBbCkTFiDs9DkPjZqHQwEOirkq7crUXHnxMm1exxZz30jAOyM5Y01GoTx3Y0jgt1r661zWTKVmXU65VN9/mMMOy84RI4ogt2SXyjDSWkL+P3ae8PPctZmF12RI69RGC8ItR7eyorg4OXN+YkayQqnHqEzV5JvjP3edeHOgI0etmxefRqJ4qkKJIWi2SosBNFOpVuDY2NY/Er4tptELqghHmdCrxlYSxR4oqIlkeRIh3GTuOe4cub+gRpJCqnNZ3zJ1rk4vkBGu3eVzvdDfvDI154q0fKljw3xq6T/ssPzwnDOoJDYZ2g957b8omyNvSz7GKBP6XcfRe/KrpiTcvMfvesXQ+oeqhbK9PgdHzR8P91Xrk27LKQ9vEX7TdviJL9XqjUeOLU1Ofighxfubd+OeuQegEu4y+MXfg7aukpuee6L9yG8r5gMAOn3ODQMdeWrdnXmVsr2bfr9/s8OUQqlWpeWNe0Eo5Ogf+Nxg2jNoPqzTZudkLczJXJCRNus8bX3CLqImj/2npbOi+ZGckibywyMnDaY9vYadUOSLC68qK1ozhW0jp4QOr/PA6NBQyA8hnJeYflW6tO5g4ajRAZHZZR1ws0wCqbglp1TeR2cK+jabe4ZDgYVJmVem58vYp9ICv8XSf9JplRcQBwH43GraMWLIVevuya+WZLcIxwAeGB2anZB2fWZx5JOvd9k+Hu5NoVR35lVGEyUbU4TR8qqh1coEHyqsjXBDd2DUvGmoZ31u+cx4CVvawaDvn32NFbrE9TnlUhdrF0u/2N+iI0jZYWDdPteL/c3XZhbJjqUGALg55unuujJKe2tRtJF74biy31TMkxQlNBGmoO/vPfVP1iyWsXYIEG4c7Kp3Wa9Mz1+eckan5f/Xeuh3VZcAAHr9gQV79hmvWoXt7+C7LWc1o58UKHAtr96YNmv9c2TWY5Xzx15v9Yy+N9RdrIm7TfpPAnzZj/AXLQfvK6g+f9CTKPIjtkbT0MHB4SNWe0tCXEF66oy0lOmpydXxcfnnWibdHPNCX7O835so8vbRNvPIyaHhI0OWY3G6vPzc5YV5K1OSpibn4YIio77MWW2Yun2uj4f7nCz9QGGNvEwhEcLDjuE9tkEEgFtzyopkGX7CAXE4gt6RVyFjGj1+14aBDh7C7xZUSx1e57JutfQnkUpJiq0/4HnN2MaL4veLpslztcQUYbRAiT0rbUxQxo6vzmUt1yXKcw69bGi5LrNYns0EAPCppd8Q8D5QWBNNaOVH5t4TLutPS2dhNBtNP0IIwPN9TYzA/2jiSApJmEP+v3SdfLJmsbyKAU6WNga854ZrW+jAZnPvQ4W1AICH6huTKOqJynL/3z8l5xaT8yQHtoVG+9reWP/F3B/+5JJbzvrTgVHzp5Z+GWfZsCLkRPHHTV/8qWZxhD8tQWCt9haLrd5qa7bamwMBW0JCcVJCaby+IE6fp9fl6DQZCkU8AKDL5/pXX9PlaXkTnTgBAKLI+wIWj2fA5e4fdXbaRtsdrm69LiczbXZWxtzsjPlT2yTrIuTC9SP0cMyHQz3rc8tJuVlGLpbeYOoAAPygKNJO8afj5pjXjW0WOnB3XpVUc2uf3/3mQAeJonfnV6VFHHs1yoQ2mDpG6MB3cislRZKDmCKM8fXQ5nVU6hJB1I15H2s7clV6viSnznmwM6HftR99smbRlBe++WS4L0OpmRWfOsqwJTt2dqxamUoQ7u+/on/ydkQrZ0fiaN/WvOP30+/dFKeT7Bsbl7HGvCN04Onu+j/VRN4H/CtY1u9wdTuc3U53n9s74PGa/H4LL9BKRYJKmUhReoeApim1KsWpEyfDeAWRY1lviHaHQg6adqlUyXH63Hh9YVJCaVJiWUpS5YVuCn9R8V/fmFeEMCjw8gqxulh6IOiTmmEVFPi3TR235ZQrJdlmI1OEsfpYMaIirAWj53TbYJR4OObx9iN/qp56LQgAaHLbwyeh5/r6b8jMTFVQfI8FTdHJ04IAgMSKK8W+450bH5xz19soLr/k1bmkKdTXZRY939cktRgHAIAkNempM9JTz8hM4Hk6GBoNhRwM66MZDwCQYbzhP1GUDkUJitQqFPEqZaJKmThVHZtjXJygCCK7HHk8qYiXbsdSYfhUlU04l5gijPHfBg/hH6oWRuNgPw+sKFAoRgvC832GPUsWAgD4DjNRLq1SxlnkLvth/yf/0/3BD0tv+icScXZXJMxLTG/3OvbbhxZLrOUxLjiu0GmzdNopEBUjxkVFrO9BjP82EklFNCWJz0/YY7fBNDgzPq5cpwUA8F3DkVSTOQ8F6rhjtd9BUKxn86NQFCYfIIW786tqpFf5iRHjW0VMEcaIESkWOlCsiYcAPN3d+2hJEQAAiJDvG8GLJdcfOB0UQQSAFN/wN5EN9mz6ERT5qZnul0xJCG6MGP/FxBRhjBiRkq5Qr88t32YZUWDYspRkAIBgcaF6FaKJ1rf309JZKEaW3PRPKPJdGx8UudBUzDdGjBgREVOE4yNyoZDDIGEAFGOL17eEp7t7f1xyquS60G/F8qcg2jPs0UQxsuTGZ3F1Yvub3+GDrujFfguBAucbqp8qabTDKArsVEmLcdESU4Tjg2CEz3RyYPeTvsGIHipRYIePvjp04J+s1xL5XfiQe2D3nxwdOyCU7Bly9x0Ybd0CBU7qwDC008gFnfLGfptpcLu7fP6bsk7VH+AH7FjeVHrgEBQruuaPuvz5Lf++mXYYp1DyRc6UGISD9h7jzj8Qqmi7bQAAABRHTrzp6v3i3MZPMghYO407/xC9AxiKgrX+XYENRCknaOsWeToaCQIbjHIOFxXYY4899p+eg3wsFsuWLVvuv19+l4OJQBBUnV4Zlz8/aO0cObGBD7pUKcXIxInnCIrrcueo0ysdbdvszZtxVRylmzwlDiUUcQULIU+PHN/gH25SJZegRKRGNkVCLoLitsYPvAPHqLhMXCGt0AMUeXvzZlf3HijyVHzWed7aRAiMf2j/s3zIrYjLQjCCZVmK+u/3Rf28uW11Rvri5FPFYOlP66m5xWjy1HYVRvT58zFS1fPRT1SppYr4nMlHnAbLsiR5oWKFLgTegWMjJ99CEEzqOz0DKFobNtIOQ9aSH0SvCBmPefCLvyeUXppQtjKSdiLjwnEcSZIiz1iO/pv1Dmct/h4SXaNNv6V15Nhr8SXLKZ18nzQXdA4fekHkQpr0KnlvjQ95zIdfYr0WdXqljOEe41HriQ36vLlSPw1n1+6AtUOVIq1sBYQQQohhk9wrllAfEQFLq6tnL66MT5l+4+TJXlB09XzhNZ3QZNQklF8WYUIV57fbmjZxAWfq9LXK5MmbHY4hMH5H+/agrUufvyC+ZJnEejin3hpA0KSq1TJWoqC9x9Wzlw84UX1exrRrMFJybR1b44eMx6xKKdFlzyQ0F3V8ozkUqtm5p+/Ky+K+zM91f/9l3e/Xofpoy2+Oi2+wrvvDH6bPvTNj/j2Rf61jCfUXO6c9Jonlq0AU5Y0Y99Dw0VdTpt+kTp2kyUAk2Fs+ph2GzEUPRdM5OZxQD11djo6d6XPvoPTySxgCAPiQx1r/LqVLT6peLfUB/2pKIm+t38gFHBnz7sIoObUvoMjbmz+mXab0OXcQaskJxKHRfnvLx+rUssSKyyW9C5+50dm+I654qT5vntSbxirLTD1eU91o+xYUwdPnfoeKm7w6tm+wztXzBalNTZl2A0pEVIpaFFhH+/aApU2fN0+iVoMewxGP8SiujEupvQFXSquaLzA+R/sO2jlAxWcnV18T4WxPx25sZIePcwGHOrU8oewyqRqRdg16DIcZ1yCEoiIhV5s9Q5VcJPuZv0D8vLmVEcW/TTvVWwf6aM/P34x77r4Ld0fWO9L1/vcpfXrh6j9iVETq7WtQhHzQFXIaQqOGuMJFpFZy03AocKPt24LWroTSS7XZUXYThLbGD1mfLXPBfQgWbeYoF3CYD72QULZSlzM7SlE87TUdfEmTmBNt+2Uo2lu3hEb7MhfcJ097hfEYDru696bMuEmVLLMzjKt7j6t3X9rs9TIksD7byMkNuDIuffbtkr6m0Gi/rfEDVUpJcs0aeavBt1YRirTHDETAeCwAAM5nAQCwfhsAgPXZAQBc0A0AFEJuCKBAezFKKzA+jNQIrB8jNQIXwAi1wAUwQiVwIQRBBC4IIAo5BmIoEHmRZ3nao0oqouIyeNoncgyCYiIfQnElFAUARRQnBS6IYiQAUBR4BEFDjv6U2hvS5t7JBRx80MH5R9mAgw+6BNrHs34+5BbZ0FiTLyiGe4bBkL03qea6vMt+ce675lk/4xpi3cOsf4T12rjAKBd08rQv/FeBDYQchpp7PlQmRVQvP2jvpR0G2mGg3YOsz8r6bIzLlHvp/6TMuEnSd+Hz+ZQU4hs46er8zGuqAxg57YGtkiSMwbiHvKaT3sH6gKU1ofSyrEUPRDLKb2kNWNom+qt34HjxdU/Jm08YH88XbPvsxIplKUEzgpPK+Fy+zxp6c5/2MWkf1FmERnsUiQXnMRuIAjuw84/u/kMl1z89qTFK4ENBf0AbJ7mN14R352naMRByGmjngMizAEAAAKFOVCTkKhPyqbgMScuTwAZGWz5mPJbk6jWSzB7jwvrtlqOvJlZepUmfgsrdjo7PAiNtmZc8IMOqcRau7j0e47G46evjkiU3kzmdgKXN1vhBcu31mgz5FVVop9HWtEmbNT2+eJncabTaW7YklC7X5UpuiChyIVvjBwLjT5t9e4Q7uTCszzpy8i1cGZc2e300R/NviyKsf/X2hZfMFxgfRmkFxo8ptAhAMGUcAIBQxQMASG0yAADXpKAAENpUAFBKnw5QoNCmg3Pc4IZtj9GuATHcghIjEIzAFHqMUKCEEgJA27uViQX6wkUooabi03FCjU/sjRDYYM/mR0K2XlKXBgCCUWpMoceVelyhJZR6XBlPaFMJdRKpTjhDCBTtrVuC1q70eXeRZ9oJXX0Hhg+9RfUNDAAAIABJREFUCABAcRJXxROqeFKbQmpSKX0GFZdJ6tIBFEfbPg3aezPm3omrJimGy/rtPR8+gqAoroon9RnK+BxFQh6m0NibPkoou0yGCaJ1wz0YCpVJhbgijnEPZi/7EamVH07Zv+03tNuMYmTJtU+ikW2EBcbPTRBpaT70PO0aqrz9DdnzAQD8raf3iMP59vTy9g13JlWtTp97J3u0h6vrU38vqn6/fVt+xXgt+tw5SVWrqbgJDWiO9m2GHb/LXPhA+pw7zqN7LMf+bTnxTnLVVQiKhi8LB2h8+V+YMf/eyI/7Iaex7fV1+at+rUwqUiTmRbMehan/++Lcy36VWL4qSjkAACHkqf/HirzLf5NYcXn0E+t4997AcEfJ2md02dHWfG/850oIEEKTElexOmv2zfLlPH85FEVSkwQAgqCINmdu9pIfSBMhcq3/vhUCAVfEQZE7faVX6DML1/xpUgF+c6Npz1MooaL0mTzjE2iPyAUBgkJBAAAiGA4ghKKA4oryW188azkVhNDgnmdo96Auby7gachxHO0W2aDAMwLthSInsAEUp6AIAYAIiotcEKO0AhtAUFSZWIwSRELJCgiw8E0FNiSwvrAQCEU+5AEA8iE3AECgfRipFrgAiiuhwCEoGn6nCAKgKAIUT6q5IbX2mvO/02+8IvwaTKNje5MIz/VQ5O1Nm0MOw7nK7Px4jEdd3XuSa65Vp0nuzeY1nXB2fJYyba0qtVTqWAAAFPmRk2+LXChj3t3yTEw+n0+jVo2cfAvF8NSZt0Zp1XT37g+MtGde8t1oXEdhoCgM7PpjzqU/i2a55CEs3r7znVm1qXUvZC3+nq3h/cyFD9Kf1kM/rbw5qpa/rHfE1ftFUuVVjvYdIUe/JqMmoWzluIXWaNdg7+ZHcaW+8Jo/EuoJz3x9u57KnruOjCKe4oybOowjde/kXvqzKAM9vgQ62nd4jEfTZt0mNephXIL2Hk//IZ72adIr4woXRWMdDdp7XN17+JBblVKaULYSI2WWCBcYv7Nrd8jeC6m4zJk34ko5/ZIAAL7hJk/vfghBYsXlsu2ZQ/ufY9wmTWZt8rQbZPz+vf2HzEdfwSlNQuVVivhcQqmP/HcVGu3t2fQoRmm0ubNxhY5UJ6KEClPoCXUCSlIKfeZEOQvdHz3qM51UJhcRygScVCM4iREqTKFGcAWh0AGMJFSJKIoR+hQAgEI/yZn723IivKCKUGCD1rp3RC6YPveuCM/1HsNhV88XKbU3SFJItNNoa/xQnVaRWHGF1EmyPtvIiTeVSYWyzehe00lH26dpc+5QJsps7QsAGB1o9rVvTp/zHUVinmwhYaz172KEKql6kk1chAwd+GdS1TWK+KiMVBsHh57r7X+N2Ze18AFCkzy475nsJQ8H3z6AJeqoVZJLWp+Fae/TOct+FP53wNLq7PocQjGp6upzlz8oCkP7/2FreC//yscTSi8dV5rXZXccfS7/it9MlYeVcZtHTm7IWf7oVNVBDe8UA9bOjHl3n+cQLEmib6jB3X9Y5Gld9sy4osXRTHUs/kuVWibD231qRhC6LL3M0GHOZ9dmz4grWiJvJyEKrKvr84CljYrPSa5eLcN5DwAIOQyjrVugyKfOuFlG2I7A+EZbt4ScA4kVV2gzp0kaywUctsYPuIAzdeYtkS8vUOBG2z71DdbFFy+LL1kudcKnE1OE0WKt38j6bGmz1kUYH+Ufbhlt+SS+dIUkuyJPe6x176I4lTprndQtGxR5W8N7rM+WseA+eRvY8N1JXVpy9RoZw8cmYmvcFHCP5C15IMqeA6LADu17NqFspSajJho5Y7h690GeTSiT1jL3XGbt3vMQ13bb/OvDC3dYEQae30lMyyXnyzmCn87gvmeyFp0RWy8w/tG2T2mnMXX6zeduLHxDDb0f/0ybPTN/1a/ODaDw+/3Q3UM7jMm110U5sTEYj3n4yKu5K38evRFyjFPeIzaYOvNWqck/EwGh4B044TEcIVRx6XPvilKa39Lq7vlC5JmU6WulBlR/1YYJir6hBo/hsCjwiRVXyI5rDY32O7t2CYw/qWq1vMN0OLw85DDEFS7U58+Xuk+CIu/s3OUfbpYUDB8mHAMYtHYmlK3UZkUeHgVd3Xu9g3Wq5OKk6tXy1pYIFeGpNItvKCdPnpwxY8YFEs7TPknX+0c6oChIvYujcxcXcEodFWZw/z9DTpO8sRBCZ/ce096nuZBHtgQIIe02929/3D/c6vV6o5EDIeQCzv7tT9Buc5RyxmA8w4P7no1ezh6rtejDjQF739grQwf/JXAh35Mfs80D0ct3du/1DtZJGiKwwf5tj9X9fYmrd/9Zf/L5fBDCwX3PTuEnCU990U8IPDOFMiGErH/U9MUzw8deFzh6aiVPHaIo8jLGhL+IMXgmYG/ZAqEYzVQENmht+MBy/A35IkTB2b3HuOv/nF275QnwDJww7vqT5cQGgQtJvnXX5/3bn7A1bZb0kfqHWwb3PWM5/qbkO0IoCALLspNeFlOE315k/KrOxdb4YXhxjFIRBkY6jTv/KLDB6KcURhR4w47fTcnCvfSjd55rOHz6K47OXf7hVu/j73M9lujlC2xw6OC/ZAx09x+qe2Zp75Zf8vRXH354/RV4xrDjd1Euu2cR3vRcCI1FuwanVm3/xzlXEV5sRPlohJwm2Tt4r+mk39ImdVTQ3ms+9KLUUREqwliJtW8vU9IGNrn2+ikxlwmsP3flz+W5QMbFfOiFtDnfiX5uu/a+2A3U99ScETiuSi4O2nsgwyGKKeh6iBJKeQWr9PkLau/fiqBE47+udvXsPUMmRiZVrbY1bop+emNQ+ozMBfcN7P6TyDNTKBYAQMVlUfqoWlnFkEqUj4YiPnvS0PSJ0GbPlBEPqEwqzFhwoXJ2Y4owxkWBNnvmFKbPu/v2q5KLogyQAQAIbOBlkPdIWRmJnvGkKOKzGfcg4AWAT00fdlyh5WmPjIEYqS648rHia/9s3PmHns0/5gKOsT9pMmtZn5XxDE/JDMOQuvTMBd89T75mjBjfRGKKMMZ/IdrsWQlll0Uvx8Qhe3zc/QXnRLshKIQQCiKCTo3y1ufN8xqPyR6uy51Te/8WUpfe9MJqV9uWcNo7ACBj/j0ew5EpmeEYpC4t6nIwMWJcXMQUYYz/QqIvDhLmqe6e+/LzdMS4sfiI7HLM56JOqwjae6ORgOKK3BU/LV/3sqNpY/tbd9OuQQAAilMp026YojnGiPFfS0wRxogxPlaaecc09MPi8SuBZV5yH4KhUBCn5mYImrXooejFqNMqCm95Pb5wceura82HXpjyZvcxYvxXElOE4wODDAxJacj5TU7HjDEuf+vpXZeTlaoYv7cUiisAgQEu2g5zUw6CYunz7qq+50Of6WTzS9f6hhr+0zOKEeNiJ6YIJ0CEzM4m+uMTotMf0eWuQOjdQ8y+dihlZRSGXaFNxwSLnF7k7Mk+0SYnvCIMZGNnhfPhYrmX+o0/LT1faStEQUjbLX2NUHGZZbe+lLXooe4PftC/7TGB8f2nZ/SNBNKsYJ6a/tV8vxX6QtHLEW0eyMhsxz0GpFkQ27qfRkwRjg+iUSjWzKZW1XKNxtC7h/h+6/mvRxM0ylsuIcoymO0N9EcnRFdELaSxjHjlNbOEfmvwzX3s8V4gSvhtElXZXPtQaONh9ngvkG6g49uHQu8dZva0woDMRtWCxcW3D8m49TeCZ3v71mSm56jO52tEVBQMTnEiwdSSWHHltAe3AwAan79itO3T//R0vib4TjPfFXWsLC8wn7fQ2xoQTbRZRqIrQH90Qhh0RCkKBhj6oxNckxGJJlaZF5hdzfT2RiDKfHIhy9OfNTL72uUNF4y20CY5cWFcq4lrMcm76aTESqxFgCCydf1C7whenklMy580yB/6QszhLugNkfNLsKxI21cKRhvXaAQUQS0uR9QSHhjBaGMbDAiGkvNLpbZKF51+rtEouvxYWhwxuwghpVRoFES+a5jvHoa8iGXEMwWJ2jQ53X9ggEHUF1drey/HF23feXj5kiLN+QrXBV/ZgxWnUYslZ0RdUMbtR+gbaujf9htSk1pw5WNUXNZ/ZGIXGkiz7LFecdiJFaaRMwsAJneXDwF7opfvtVDLq7E0mSWzIYSBQEBNKth97TDEUJfVIooo8vYEkTnUKdp9ipU1iE5+ri3XYOCaBqiVNVjmhG1zzgeE7Mk+od9GLatEU6R1PAUAiKM+9nAnoldTi8qBlHBr3mBjD3XhJenkHMmtu2K1RqcernWQbzIiiTrFskpATaYzeIGtN0SuPsOI7gB7sBP6QuSi8siVKAAAhlj2eK9ocWEFqTJWAcHs5BoM0E/j1TlERbbUjD7R7vUf7yICHKIkieocLC/iZq2CyOxpFf2nTEZovAbLTMAyExDVf1I1/qGjq9Pnf2POJB15Qh8eRQhMcU20TVynloka80KRtxz9t/nIyxnz78mYd/dUVdCeAnhBGHELwy68JB2Nk1MyV7C4uLp+yAnUwjKpe8Gz4NoGuXoDObcYL4mqfQcUoe9QG2H2UJfWoEnyG+qemlKTkVpcIWlBOAu+38od7SFm5ONlMqucc22DfIuJnFeC5UnoqBMG+mhmfzuCY+TyKoSQcJwVLC52XzuaFkctrpCkO8eIKUIAAAAsL3qCYogBIQ56Q4DjRE9IFCD0BgEvQJoFLAcZATIcgmOQ4RAlCWkOITHIn0oRgyJEcAyGGITAYYAWBRH6QuT0AiRBC2kW+kMgxEOWhbwARIAQKBAhFEQEwwACIC9AAUKbW7FmDrXyVBVp0eUXHX7oCYjukOgLQG8I+hkYZAAvjH0XUBDEIZfi1oWKJROfNmiWt3mg1SuOeoVRP/T6oY8GAEBfSHAG4v5xH4j49yb6ab7fKgw64LBTMNoFh0/76BqsWFo3QZ/Pp9VqhWEX/VkD3z2CJmq0P5HcPkJ0+oVhpzDogDQHWIE3WqkVleQsmT1oTiGIgs3DneiNUGP5eL5o2879yxaXasfvNyIM2LH0BEBizJ5WYcCuuktmv9NT0px+LGEqG8qfv0M94x4ybH+c8Y0UXPU7qZ0EpgTIcKLFJZhdot0Dws8XiaOpeiwjAUuPl7bYhfeaRhuaoicXlEqzZ5yDYLAxhzrxkgwZx46z59U3wh7tEWqytNXy27kAAASzk93fjldkEbV5soWIoz5mXxuWFk8uKJVXskIw2pgDnXipnE8GMhy7vwPSLLWiWtLuVnT6mT2tiJpSrKyJpmzFt0URjvz+vSXz5kNBBABBEAQKIkKcptKUJILjQIkjFAEIHNEqAIri8SqA44heBQgM1SpRrQJ8abUIbtgnDrnCOgygKIIhkBcBAAiJAxGKniCSqMXzk1ElieqUUKNENQpUq0TjNQA/+wQGaS74wk5hyIHEa8bSriGEiJJCVBSiVSA6FR6nQuJUaJwWTVSfmgOE7JFuYdBBXT4N1Z/hoGJbTcyWkwgypp5RRKfCErRIvBpJ1uPJOjRNxx7vE20e6rJaRDmJHUZ0+wPP7wIQAgRBSBxN1mKZSYiO4juHyQVleKHknrruP3+EcSJCEWiyVvTQqtsXydvdhwm+9oVgGkVIXPPjqwAppYyZCAWbRxxyCCNuyPAARRAE4Q1W6A1pf7s2EgF/6Ojq8PnenDNrogt8v91IzimmrprBtZiY7Q2an0XTuAN4n3gfTdAS1Tnk3OLoC7YFn/uMtbioGQUAQlSnRNPjsfR49BxF62jfZtz5h/iSFbkrfnJu/4ox2GM9ofeOkAtKERKDNIdQBOQEBEMAQKAgIiRGLq4461d6HgSn3/ebjYorpmMZ8VhGApqsk7fHPyWtx+J7aovmR1fhpVPQyMn72PvQF1Q/fAWeG7ExYwI8P3wVUSqQOCWYXaBdIbdFF8N5HnsPQTFETSIYCiDAi9MUN0hrly04/cF/7QQoisapAM9DRoAhFiEwACESr1HfP3lLFr7DzGxvACoCzU6C3hCAAPpDgBdhiAW8AEUxvBwBFNH85BpwZvUlwPD0tnrB7iVn5gOGAwCI3pAoQIRmRYYHPA9pDggw7GWHQQZREJAVEAyFgoDnJiMaBTGzEFEQIs2B8DWeIOB5ESKiOwAAOCUHABigAYSAEyHNAgDCkUQIiZ+SKQB8SblywSQtYr7xivBrMI2KrgDzeQsap6aWVUZkchRE5mCnOOI+V5mdH77Pyp3sI+eXYDmSnW2C0cYc6CAXluP5sp5kCJkDHdAdUFw5Q97+K3wiZI90i06/4srpUSabh00iyrXzI7fx8p1mrsOMIABNjcMyE7CM+LE3Qm+rJ+eXovGTK2Yvxxdv33lg2eKSiY6DZiffNyIOu5Rr54tOv+//Nuuf+k6EMxwXrm0QwVA0XsMe64EcT84qxHIlm55Om5/ofXu/7valAADopwWzU7C4oDsARQgQBNWrqOVV4Qt52mva85Sre0/eql8lll8+kTz64xPkJWVRGve+mp3RxtYZlNfPmZJaBKLVQ3/eTFTmELW50criBfZ4r2AaJWYV4kVpUc3K5mGP90KO52fmanPki2L2twn9o1h+MrmgVJI58SsCdPCtg5Dn8aocojzr9B1/pHPY3cIe7Ubi1ERNLoojSKIOoACN0wACR+MmWdnYk/2h9w+jOhWWlwwQBNEpAIKiWgrFMaCkEBUFMBTVqwAK0MQzrNm+x98XXQEsPR7gKKLAAYEDCBCtEgCAUjhUkAAAVKdEMeTUeQYAoKJQBQEAQBN1ZwWAfltOhBdUEUKaYw92wCBDrZz8jBWGaxvkmwbIReVYtgSDftgOgKXLMV/AAMPsakY0FLWiWt76IpidzK5mammlDOv/GD67E/+8g5hZgBdH2xtdMNrZuj7l9XOnZLmEQYbZ3RyhXfTx9k5DIPDa7Am9g6F3DylvnCeMuAWjnbyk1H3/i/pn7o7mJAc5gdneoLhmFgBn2vrmlyCUHLHevU2q3DS8YLwzvSCetbHwDdX3b/1/VHxOwRW/Gb/5OC8E3zmoWr94qsroCKZR9liP8sZ5UyWQazBwbUOKVbVRegcBAABCrtHIdw3jpRmR+/XHRQwy/r3NuDNEzMgnKuXXvBWtbvZYDxABubj83JN9REDINRq5tiE8P5mcVyIjhki0utnjvQBFqaUVkuL4AADCoIM93IUoSWplTYRLKAj7FPe1id6gYkU1miozXilMTBFGC7OnVXQFqEurIzzVCaZR5mAHUZNLVEno4QlZntndDCCgVtZIdnJAwB7pEkyjiqtmIlpZkdmCyOxpASKgVtZEY6fiDbbA/lbdjQukPifjiuIaDcpr505VCW76k5PU0spIYu2cLFu2Y/fRFUsK1OOfHcPHwXCYaOjdQ8q1872/+0C1fnGUZ4jQh0eVZ1q9BIuLO9YDIVBcPi3y5SOM3+dDP25UrV8U4fVQ5IcPv2Q59nrmoofSZ68HyNkLpWAa5bst1KXVkqZxHmQc9yeBF5iDndAbpC6bNiX9QPhuC9dkRJN11MIyeQaScNSoRq3mGo18jwXLTCTnFct+vzDEske6RaubmFOEF8r8sQlGG9tgRLVKclGZjD2W6Amyh7ugn6YWl0tVTuKol9nfAQSRWlkTucckfA4RzE5qSYWE+Luzbh1ThFEiOv2StmB8+xBelilVnTD72oma3EisdmcDYWjjYXlBXGEEo4052KlYWYumSo6EPm0agPmiFUDAzsrV6qI1oPGdZr7bcup4NBWEt5aKqyeJ/wzzPy1tXo57bsaEISTh42B4ZRSGHILRzvdYsOykKJUEvb2BWlxxbg4J5AQEQ6X+ovx+P9VjRygCr5CQJkE7jH2f/lrkmcKrf39uA3T6s0aiMjuaqMWzEO1eZk+r8sZ5U6YLv3RhYOnx5CWTOIQiJHx4xdLjyYWS28rDsQ71YVEGG3uiF8tLiSoShxfYE73CwCgxPR8vldm1SrR7mYOdCI5SSyLaHZ7FKeVkccmIJAg/jNAbIpdVYukRt3ASRPZoN2+wk3OLZFibYh3qY0wCb3ZG37c1tLWOH7DDqBvzQgjZRgO9qznaCZ1JcNOx/8/eeQZIVZ19/Nx7p/fZ2dneYVnK0qsCoqjYUAlRY2yviUk0TWNee2KJb0wsScQSFcGoiIoKShGQ3tsWtvc+O73X28v7YWBddofduXeGZub3affOOc89t53n1OfPhuPSH7agmGHjtxb0rIlpswc/cIaaKPr5YXxvY3jlzgQLSfc4yKquBI0MENWDjXxykP/DZe3VX1T+Y65p34qhqq0sG1l7kKN4C7WPAOMORj45yJLJtMlxHNlowjZXJtEgS1BCcp1LYV4WTVRumo3gjDMgPD/NEMfbhb0PLE7iexoYD8+bw7JkZSe+p4Hv6VLCvClGAcnRJz78KLtphoClPcOhO2xsAE3i+BsAgPVHILkkztHaF5pbflFSlCM/a2LyUIv0zLVnkgXjuTBOd9gTLCdSaKRNrgSNDEEyewx1sptnJihzxh1THtyCutqHBimFINmSqfh3tUksIWxQy26eia07zOGJBgwbjHhSvuzmpI0ogOiK8YsMvqPlMSwopAlNqSKwZG6psEFjSCqWLi7nPd8JQeJZYwaWeiWdlCNMcVEgKs1OeogWYk+D9Mq4bLaGQpsstifLhg4JDsBYvPCgZahRkDwDF8Y5jIwzIO1ZgSBe0fXiQVSWQ7UICYAnURnLbv93/qJH2tf/vnfHSyx1OtaBUQOp5UkIXTYIWKuQ3TKbbrUk0WaKFAJIOcIUP0xYbxjWyOOMa/VUfdOT48fpz75hkTzcKp0fY6JIMr8MMWroFrPwggIAAIANatYdTNDIEKQLxpPHO4TlNUy4buqDW2k8ULdyaaD3+CmDiyaOGnSXL7BWIZ5WlFybKVLwJeUIU/wwgXVK6TVT4km53+WuDwR+O7ZkhDTS66bGXNaBFKSL54xNPBaweFI+3ZLkjhFSlIEI21QKAABAJNeOvfXV4uuf79r8VPe25xkyAgCQ3TA9eQVMkeJiIeUIU/xAgeNSkGc57n/rGv4+eZIUHulbGGHNt2TeOKrRlODYJmzUSEYLfiEAJCfutXlnQTf2iqkPbuFYum7l0kDPsaSUKkWKi42UI4yNmyApoTIlKS4hPu4zyWD4jnzhggywXgkbNHR7wpNnydtIkFwQqXrM0pdKbnyxa8vT3dteYEj0QpcoRYokc5F+exccH0U+39TyRkdXgIprSVuVz/d4feN3dgevfsE+p+udru44TzGEHXYHmXLViRGi6T83Nq+YNiXBxbOSmSVkFd8lmpcYujELpz64hWPI+vdvDvZVXOjipEiRTC7AhnqTybR+/fq6ujqlUrls2bIlS5YMT/Piiy+i6KmG55QpU+66666Yps51iDU7jn9q6ncT5M+KCs8WfHIwh92ebTZ7rlz+P0UFKlFcq66tGP6V2eLA8Tvy86bpeGxsr/b5N1qsCAT9OC93spb3Suh/tXcSLHtLTtYkTcKBqQAAp2ONJsXUeeOphiYHjn949oBqccLY/eG/f6NdcX+ywoYlwsjqE4nj69jfvfVZw8QbCxY/CosSDSR08WPH8SwZ78vkztxQ7ySID3r6rsvMmKFPKGDYIbdno8X6eFmpgCINsN3u2ONw/W3yRMmI0wFng+a4Nb0mMQzdW8gjhNYA9YHAd3bnE2W8JWV22B1KkWhBOr+oDhdvZJnHHnssGAzOnz/f5/O9+OKLK1asuO+++4akSU9P/9nPfpaeng4AGD9+/K23xg7wf36Cbodpel2/uS0U/lFuzuWG0QUtuyORdSYzybL3FxUWKeMKz0ay7CarrdrnH6NU3lOYL0fi3aBDsOxmq+2w25Mrlz9QXGiQ8NhghDLMHoerORiEIWhpdtYEnnFhvrXZT3i8CATN1OuvMBpgHL+0HGFrKHTFvkMNS67OlCVB+zD4/BeKn8znFczlHHGuHSEAgMYCPdtfiDhaxy57TZV9rrZ2XVgiNLPBYmkKBMep1Q8U8w7qPeAITSi6qruX4biHS8ck4r2Oe7wbrbaZet1tebmCW1tHPd51JvNCo+H2PCGSHRwA682W/U73A8WFAjx6bwT9pM+UI5f/T1GBiE+T8ZjHu67fvCBdSLEvXkfIsix8uiXy8ssv7927d+fOnUPSpKenHzt2rLR0lFbD+RTmZTjuG4t1n9NTrlX9orhIPFpjKkTTX/Sb20PhJZkZ12TGu3ivNRRaZzLTHPdAcVFxfE40Sj+KfW2xWjBsSWbG1ZkZvD6VAEVtstqagyGtWPyj3OzxfPwZw3G1/sAxj9caCjEIMitNf01Gxgj7EIYQpOheNGKQSNIkkvjdf1K49uCRpdlZj5SOSYo1fEct0+9R/uLqpFhLhPPgCKN4mrf1fPfXrNl3585/CILP67MbAROK1geCHaHwo+MEBjOr9vnXmy0Uy91TmM9rkGYwHMc1utxbPF4Ygh4aU6wbNcTX2akPBDaYrWNVyrsK8hGhQw4NgeB6s6VcqxHsR3c7nJut9h/n5Swy8g6gYcawD3v61GLRgyXFvD7zxkDwS7OlVKW8uyAfFnTtcTrCCxA0AR7kQux2u9EYO1TmihUrlErl3Llzly9fDiU84sQC0BdGAwwVIEkLikcYxkeSborEKNZPU0GKwlkWYxgIAAkMYwwjhmEYAJxlZTDMAkCxrBxBSJb1ksQWq1WKIGII2DDCTZE+ggpQVICmSZZlOA4AgJwuLs1xEZpe3dP35WWzr8n43hfSLNsdQXsjqAlFLRhmxwknQXhIciABytBvdnRtv+Ly+YaRxgFolm0OhdqC4eZgsB/De1GUZtlvLDaCZU03XRf/zdGKxfMNaQwHjrm9Pz5ywk4QHTdcmxZf5xKBoJl63Uy9LhQKyVWq427PH+vqj3t8c/T6j+eOPuRIc2xXOFJB+twEiTFM9CAEAARBDMcedHlenzpluj6BUKgAAADCNL2qp+/RQT7vi36ziyBG3jJxNvYgAmUKAAAgAElEQVQ4nVdnDG3ZSC8rC2xcy92zMM6diwN0h9ASNY8Wz8gwyTIUB4aJN6rzZ3Vtebrpo5+OXfaqLK3oPJ78FBTLtofD1T6/GcUQCArTdLpUOlOv+1UJb0VcG45vMFt7IpF5hrQXJ00YtaU7AnX+wNcWqxaAR8ePS6R51xgIrukzlapUz00cL9gFtgRDH/T0lamFGxnoR745Pa79SIPxkOS7XT0Mx/2hdIyWT2ugNRRa29dfpFQ8N3E8r+6jMM5Jj5CmaY/HM/x4WlraYM9cVVW1ePHiY8eOTZo0aUjKX/ziF+Xl5TiOr1q16rLLLlu7dm3ME+3evfvGHXu0hQUwAAyCwAyTmZWl1OnkCEKzLMNxMgQhWBYCQArBUgTSiiQaESxHROkSkUYsUcBwnkKmhkU6sThXJhHB8LNtHZX+QPR1YTkuuhYl+hhCNO0gyTyptESh1EsQvUhskEoNYnGmTJIrlWZKJIozJwW9FPVQXWN7BM2SSYc8RgiCDGJRulSSKZHmyuV5MkmBXF6sUMAAUCz7kdniIMhHiovUZ8Yx2e/xvdbVTXMcDED0mSEQZJSIi5WKQpl8okpRqlJtsDm8FPVIceHImwEAAHaS/GVdI316uU2aWFyuVhUo5DWB4K8K88edRX5hBH5cURXhAARAjkxKsuw7k8vVCehKP9LYXBMIaiWSTbOmC2sJRqn2B7Y6Xfs9PhgCu+edUmIK0vTsQ8c+mT5ljqD2/qT9h35TVPjboqETJPT7e+FJefD8s4anicmEfYfm6fW/KMidn5boVgcAwPwjJ9QwtDjDOF+vm6vXJViDPNPatt3pWZ6VkS+XT9eqJ6pUsdwD56n7ynlsZeb836ZNXj6CtR1O9+8am3+W//3olgxBtCKRTizSicU6sXiSSimL2218YLL8taPz10UFk9XqSWplgZx3/OjBlO8/BAPorSkTF6WNPvcxAlYcv+zwsVyZPFMqud1ouKtIoFBiSzh818l6g1hSqJCHaJJmwWV67eM8220nfL7HW9p1YvEElZLk2DB16mMnWEYnFr1ZPnrQpc+t1q+s9hypdIxSAQHAAMh9ur0eomiC5QAALMQGSfqLWdOHvBl2nHi5s5sC3NKMdBGMeIhTGX0URbAMAIAFwEWeWieI0jTKnPJENgIfq5AXKxU3GI1SGAEAkCzroIjorxjDDphCWTZInfo7THMRlj5VNpohTsdU8tPEzwoK7xhtcPucOMLm5uZrr40hf7xx48bZs09VRq2trYsXL37jjTduv30k3XCz2VxUVNTc3DxuXIz6paKi4s6f//zl554bODJ//vzsbOF6eGGaHr7IpSMcXtndO02nvbsgP556hWLZD3pNNhx/qLgwm8/3uc/l3mS1/aq4aGKs6TqSZUXwWf3bSZ//037zL4oK45/qI1l2YLacA+CjXpMFw54oKxU2he4LBPRa7XqLtTUYemb8uES8FwDAS5B/aWl7dcoo2/vORpCiv7JY2kPhcq3mttycGn/AR1E3ZZ0Klv/bmjqWA+/OEKIejjLMis5uMQRdn5kxZI0S3diPbzihev42XgZfa+98oLjwqNu70+GYnaa/Kz9PcNsfANAYCB5zOO8ZU3zU4z3m8UYYJkcmuyUnq1AhpNNJsezzza1/K59oxfCT/kB9IBCiaYplCxSKGTrtnDT9wKuCubu6Nj8hVmWWLP2rWHFWX/KnxuY/jhs7MJONM4yfonwk5aOoAEXNS0uLf1AdALCyqyddJv1xrkAdhsHYcXxFZ/ecNP3ynETVNI97vJ/3W6bqNLek6dOFrkSjWHZld29DIHRtZsZMvRYAoBeLdHxWAAAAesPoM83NDAeW52VnSaUAAAWCpEukAAAVIjLGMXTx99b27+zOEqViokadIZWKYBgAIEcQw2kVp2ypXAxDEgjOVQyd/lzR2fVeV2+eXD5Vr4m+0EpYrBKdemEGrMkQKF16apLeIJYqRcjVhw5LIKRQIRdBEAxB+tNXLYYg/enzymBEe7qiVolEmtP9K41YpBGLBltjWS5LJlFLR1sHwDeYd1Lo6OjIz8//+OOP40lsNBr37dsX86dzrT7hIYiXW9peb+/A6HjjrG+22B6pqesIhXmdqB9Fn2loWtPbx7+MnJ8kn29sXt3dK1hJwoZhj9U1VHq9Qg1wHMcFgsG3O7q+MVsTMRKFZJiHa+o8hJAQ+1Ve3/ONzS82tXSFv38ELzW3hqhTGgKHXO7cLdt9cQSkj8kGs6XK62NY9vcn64a+FSzrf3wN1WnjZXCPw7nH4Rwo2x9q6t/s6Iz/fRvOHyqrB//bG4m819X9TEPT843NjQHeggPvdHYPf5k7QuHPTf1vdZyhmMHSZN/u16pen+/rPHA2a36SfKq+kW8ZRuCzvv7/9PQmy9q3VttvT9aaUTRxUztt9gdPVO5zuhIxwnLcZovtDzX1my38XqrBhCjq351dT9c3NgcE6sMccrmfqm9c09tHsbzrmEMu99P88/ZFIn9uaHqqvtGGxSUdMwJxqk9cAEfY19dXXFz83nvvDTm+f//+uro6juP8fj+O49GDW7dulclkTqczpqlz5whpll3R3vmXppb4q+Nqr++h6prtNjuvE6E0/UZ752ut7cLqvs0W26O19c7Tt0sAX/Wbn6pvjCRQ83IcF6So31VUNfgTEHY5Dctxj9U18G1JcByH0vTT9Y2bLTZ62Cf3TMMp+SSMpsdv3/W12SK4eE/XN0at96Po/zW3DvkV+64m/M4OXgaDFPVqa/vgIw3+wON1DX9tbhXmrd9qbo1590iG8RK8DWI0/Vxjc/zpA70nqt9Y1LPjpaFCTqf51mrbaElCa2mALVbbG+2dybIWoem/t7S93dHF8K/0B8OybDAU2myx/bG2vtrrS7BUu+yOP9Ym5A4Jhvmk1/RobX2FR2B7t9bnf66x+a2OLpR/XVHj8z/f2PxWRxevWs6J46+1tj/f2JxI0+TidYT33nuvRCIpOc21114bPX7TTTf96U9/4jhux44dBoNh0aJF8+bN0+l0I3Qcz50jpFi2LxLhleVrs2V4FTwq/2rr6OV5oigEwzxaWz/QmRCAjySfrm/cm4CFKO2h0K+ra7rd7gTtRPl7S9sxtycppqL4SHLA0zxZ33j70ROCTdEs+0JTy8C/G8yWLdYz6iYWJXy/WcVXa+3PDU3DD/ZFIh/2CBkhsPv9Lw3z0InwWmv7CDKNw6Ewf9v6h2tXLkWdHTET/LG2XnCPPCb7na5nG5sT1tb8nhqf/w819U1Cu1DcID1ChmW/6jc/Wd/YFkxUnvCQy/1MQ9Nmi03wlTIs+2W/+ZdVJwXXG52h8J8bmv7a3Orn/wQbA4HH6xr+0dYe5iNkGKSodzu7n6hraBek73jxOkKHw9E1CJPJFD3udDr9fn/0b7PZfODAgRMnTows9/pfLsybYKN1h90RIIWIjg7mO5v9xaYWmmUTF+blOO6jnr7kdhc4jlvfb4k2yY97vFmbtzkS6D3vcTh32R2DjwwfvUE/O4R+fpiX2Wf5dLlGJRQKPVnfKGAU62z4SfKv/D2r4+SXlf+Ya6/6bPhPLpyI6fsTocrr+9/ahiReNcWyK9o7X21tF/aVDRHmxRnm7Y4ua8IDfRzH7bI7usNCms4DMCy7vt+SyKhjTzjyXle3sLxd4fALTS0Ew/DKFaboNzs6N/Afy7l4HWES+S93hBcDpsipUYvEHeFeh/P9rp5ECzSMPzU0MSyL0vT47bu+7DcnYurZxuYhH3CYoh+pqRtcUzKekO83q9gwD3f7Tmc3ry7XyIRCoYMudyLDaMN5sanFzX/KFnV31636UeuXv6VQ/5CfPuvr33lmkyJxWoLB352sTWR6dThmFE2KI0xxoUgp1Kc4H+QrElq2PhgfRf2ypChZ1gaAAIAh6KmGphl6nbCAGgNwHDdkSa1ShNxXWPBu1/eBRuE0lXh6MbGnPn6zc9L0FV5fIgUbwsJ0w9FY+5cE86uS4g97+vjmkhuKJ//sC6k2t37VrUFT1eCfflqQt83mCNN08soIxqvVj5eVVvr8SbSZK5cnuP45xSVByhGmuFhYnox18EPoCIfHqFQ7Hc6NFtu/Be2XGKDG758aa9/hDL1uSNwD2U0z8F31HB5vLPUpWk1DIJBI2YZjlEptOJ4sa5kyaYCiBPgtCBEXLXm65MYXOzY8Yj74Nsd9v+P/sbKxb3cmOVJ5gUKxkGcsyhQpQMoRpvhh0xYKz07TP1B58uM5MxMJcwUAaAmGrj+9E3EIQxwkkq0XT8wj9jTEaVkMw1Syt/PeXZB/wpPMXuYDxUWd4YiwvLqxV0z+5cagqbL5k/vJ0CmN+1y5/H+FRkFLkSK5pBxhih8yN2VnPVnfeE9h/pX8AyQO4a6C/DgVRQAAsltmEztq4+8U/jHZLiFTJl2Wm+je8MEUKRWCA28CACQq48S7P9SVzK9fvdzXsT96MJEwZilSJJHUixgbLGw7HWEtxSXMivZOD0m+OGnCeT4vkpsmmphH7I53pjDB3uqlAQTnLnio7La3era/0LfrZY4RIsOZIsW5IOUIY4NHnI2HX+qq+5Amw/Gkt3XvbDz8ksdayess/a1fWzq2sizvGoGh8bC/h2+u/zaOe7yvtLWvmzf7gvQ85D+ag++o5VDi/J/6YkadP2PKLzfhPlPjR3fivv4LXZwUKQAAAHnhhRcudBmEY7PZtmzZ8uCDDybdslyVlVm4SCo39DZ+Zu/dI1fnSuUjReNV68cY8xeE/d3d9WvCvk6NYTyMjN7G16ZPYGi8t2Gts/+QTGGUKuIevuM4W89Oc/uWkK9TqckXiflFkqTIUEfVexCMyFVZEJQcJ0GSpHTUgH7nETdBLjl45N0Z0+ckI5i1ACCVjLX7GZNHfH5FCkmSlPAMSnmegcWy9Ek3sjTRtflJqTZXYeSt0XpJQFHUkAfBshQEJaRXxbG0peNbCBaNXB2NTCTQ11mzOi17JgwLUx/iLJ3bg65mTfp4AZn9riZLx5a0rBm8T9qxjWVImTJeSbtT2TiO4zhktGDuF0CPMImcHz1Cmor0t20M+7ozCxdlFFwxavqwv9vS/i1Fhgon3qFOi+sjZ2jc1r3L76xXagsLJtyGxC38jYXt1s5tBOZV6Ypyxt4gEserGsHQhMd6wu9soMiQSjcmu2SJRMZvBqin8VO5MlNrnCRXZYOLTKGe4bgbDx2dqdf9bfJQYZPzCesNB59dp3npp7COt5qHYM6bHmHiRGxN7V8/qi2+rGjJM7DoImpFJQ43SKGeIoKWjm/D/h5DzpzskhhqBPFAk+G+5i9Dvq78smWGnNnCjAQ9bX1NX4il2jHTfy6WCPhaOVv3LqfpUM6Y64z5CwSc3dy2Sa7JLZr4E4iPD3aaDtq6d+WMud6YP5/vSS9eYd4kcj6FebGIy9axxWU5IZUbpi3+26jpaTJsav06EujWpE0onHQbAHG1BIOedlv3DooI5Y9fpk0fXSflzIw7KSJgyJmdWXQVDPOYc4oE+uw9ewjMK5ao0/Mu02fGpTrGMlTY3+1z1EcCvQBAJElp0/LVaeP0mVORC12pPdXQVO3zf7fw8kSUHJIC9sVRDiUUP7vqvJ3xEnKEAACGjHRvfRZ1dYxb/oY8XYg85DmCQN1ee03A1cQyZMmU+2SqLF7ZOY4Lh4OYr87VfxQWSfPH3arSC7y6SKCvv20jy1BFk+5UaASOLvhdTdbObVK5oaj8bgGfJ8ex9p7djr6DuWNvEOCNgp62/raNSk1+4cQ7+LvA3dkl12YULOR70igpRxgDmkbxiAcL9ZO4j8B9NOrDMA9F+hkyTBNhmiE4joVhEYBgjmU4joEgBIIRwHEsS4nESpFEg4XMAEKmXfkXLOzEI3YCdeIRN4l5CcLHsTFUUUncz9Dootu3yFXGISWJeDrDgd5QoBcLWrGIgyICgGMBBEMQRGE+NGy/7v4jEvkow3o46vLaTgZcjSFPJ4Y6AMehIbNEqr/6np1x3pPTdtz2nt2Ovn1+Rz1FRZb+isd+8CihUBBmvH5XfX/7Vq+1smDiHeXznxo1F0NjeMRJkWGGQhkaI/EAQ+MMjVFEkCT8jt59V925BRHxG/j9ot/8dENT5TVXDcj9UIS/o3rlxMuf5HtRMelp+qx40l1xJuZQIvDkWvXTy5Gc2I/S0bs/s+jKpBQMABAOmACSljxHyJ6fZQTOmq9Me/9ZeO1TxinLzsPpYsKyVMDV4rGewCNOAIBEpkvLnq3PnBL/8MwAQU+btfO7SNidXxqtwQW2xnyOenvPLpFYWVR+l1gqUNHJbamw9+zWGMblly3j5YSiRF2g23w8d9xS/uOZIOhp72/7RqYwFk++B0Z4jNhHXWBGwYLskiV8TzqY/xZH+N4/7nnkd/dReIAigyTup6lILE/GsiwNQTAikoklSkSsFku1cqVRItWJ5TqJzCBX5yqURlgks3Ru9dlqccxNYT6SDA4+F4l5KCIsV2WJZVqJLE2qSJPLjTJ1pkyZrdDmKdS5MHzGYw55O5uPvwo4GAIQjrkAABzHAI6DYAQAACBYpshUaHIV6lyVtlBjGC9TZQIAKCLYWbNKItOXTL1/yOxdONDTU/dJ2NdNkgGOYyEAAQgSiVUqfbE2rUyfNVWlL+6s+VAi1xeX3z3qraPJcMvxf/ldjSxLAY4TS1T6rGlyTX7Q3TJ+zh8kMh3fZ3Fy3wtBVw0AQKXJl8j1k6/4Szyzj0FPm9/ZgIjkYqkaEStEIrlIohJJ1N11H1rav1Wnj59747u8ilHj919/8OiuRfOnaE+N9Dr69jcd+ptYkb5w+Wd8LyomW1dOKZv98NgZv4gzPb6jlm6xqP5wU8xfv313YvaY68fPfUSpFSjiOpjtq2aoDBOKy+/MGXs9r1GBmBxcfxtFBEum3JdbulTAKzGExqOvmls3FE36qSFnVlr27CH9EtTZ3v71H1Q5k0tueAEWjx6uqHbvU/bevbmlN0tkepoMwyIpxzKAY2GRlCbDEnla6YwH45z/Zhhy+6rpMnX2uJm/zipaLJEJn1R29u0/sfUhpbZInz0jq/jW7OK5wuyYm9fXHfw/hTZPpSuWKNIlUpU+e2ZWIb9xhe66DztOrpKrsrQZ5dEGDQKLJXIdAECqzCycMLpwZu3ep4PuVm3GRLlqpGAXECQqnfnLIW0mW9f27oZ1MmW6IWfuqUrvLJCYa3Avwu9sBADoMifrM6eNkAtH3eyIC49pMsBQGMdxhrwr0rNHGeUSNll6EUEzkNYwXqbKlMnTpcp0iSwhgWkIEuszJ8tU2XJNnkJ1ahuW11bd37Ypb9zNcQ7Nk3igq3a1RJ42ZuoDBOZWaQvV+rFwHO1KS8e3XtvJcbN/K5XHjo6RljNzzLQHFJoYccIcfQf6WjaUzf7d2fLGtDbh8sdEp/pbXFfdxxQemHLF88IasPrMWTOues5pOuK1nRw/95E4c2kMZRpD2fDjWYWLCcxXvuBpXmWwYviyIyfemzkt6gUZGuuofl+dNnbmda9bu77jZepsUGSosPwniFRp79mdVXxNPFlkV08O7Kqnm82iWKtmisrvKppyn6N3XyTYP27Wr+N/fDEpnfWQVDVGqTG2Hn8dRiT545crtQWCrU298v/svbuzihab2zdjYZtKV5I3bikiEhhUb+K8RynMXTb7d35Xc3fdhwTmgWFxet689NzLYESsyBg35YENPd+9WL96+bgfv6HIiCHEfWbZ/kps/+2EeY+J4vCaI4Mgkitu29B6YoUhe1YiXhAAkFF45WW3fmRq+UqfUQ5g4cPyeRN/DERiW8/+3DHXwoiMwH0w/655ztilQU8rTRPGvMtFYiUWcUaPMwwWpwWlvigcMEGwVKocOjJME0GGRkfIG/R14xGbWKYiMSefKoVx9h+WKTM4wAVcLQNHYUQmkow00T7g4wVyjkKdnh/OddDtSNDceOTvfc1fcVxcgXdZlulrXl934AUc5adJFPJ11R14wW2pEFBIEg80HXnF3P6tgLwDFuoOvOCxVgm2wHFcMBg0tX7TWfufRIwM0NPwqcvMTy8Jpek5u/e9clpxyWU+UbvvWSxk4ziOIiNtVe8kpWD23n3Rx9R09LWAO15NBuJER+DZdVys8M1NR1+Lvl0E5muteKuj+n2aEq6PEXC1tNd+Hv2bJILdDWvrDjzf37aZZQTKjDQe+fv3xt2trSfeqD/4oqPvQJxfxBBaTqwg8e9FKykiZOve1XT0tcYjf+9t+jJ60Fm/sfIfc+3Vn49qLezvba14S0AxYoKF7Sf3PMX3y40JTaEtJ95orfqPsLs0AEOTXbUfNR15ZfBN4wuB+ZqP/6v52D8FG3GZT9Tuf7a/bbOAy3GZTzQe/jvfvHjE1XJ8RfOxfxLY0HDtfEmpTyQETWHNx//VcfL9s+mLDsdjO1l/8EW/i5++DE1hbZX/bj3xBkMLUWiz9eypO/A8jgoX8PPYTtYdeCGRLy1Kc+Xq/rZNCRqJEgmYWk+8wSsLxbJLDx19oLKa4ziawlor3uxuWDvwKxZ2dNWtSUrZWo6/HnVULMvU7vtz/PVm8KUNxMEYcktddWuw8PdiztEmUfxtr2GwJ/e9OOSQy3ys4dBL7VVDpbDjoenoawxzxpvJMpSte3fD4b/F3w4YIBLo76z9MOZPg99/zN1T9/6tbesfpvFRJE16m75w9h/hW4yzQZHh2n1/Dnm7EjfFsmx/18GTu58I+RK1RmDe5mP/bK96V1gVEQVH3W2Vb7dWvEkRAjUxXOYTDYdesnbx052O4rZUNBz+W1/zVyzLQ30JR93tVe+2nFhBYMKVjVOOMCFoCuflXViWEfaKtFa8iYaEKPAxNCn4vTwN21W3pqv2owQsnKKzZnVP89bE7XAcx7LMyT1P8e0V/aa69oaDRyiWdVsqavc9i4bOECEKebtMLRuSUrymI68M/E0RoZN7noqzeqK7Hf6H/8NiQ9tVjr6Dw/u+0e5s0CtEeP3kvr/EPE4SQnSynKZDjr6DAjKejfqDL8bj4xma6N7+l5NvLQ6Za0dOWXfghcT7DQOwLN145GW+oxGx7LChUIhhyM6a1e3VK1k2UXGooKej8cjL/W2bEzESHeJqr3pX8KiDo+9A7b5nE3aHPO4Gjnraqt5pOvoqFhai25VyhD94WIpMSJ/T2rXD70pcEpZtOf6621KRFGFejuM6a//jtY9S9w3h2cbmWbv2hSgKCztiOjyvvS6xFsMpGIZsOf764CORgKnh0F/jzB5etRv98uiQg5GAqbdxXazkrLDaqrXqP2G/EGn7mLAM1XT0tWRZ4zjO1rMn/j6cp3VX5T8vsxxdNYLvJDB/w6GXklS6U3TVrUlweGOwHqHP0VCz9xlhzZoh2Hv3tRxfkaCRoKe9teLNRCzYuncJnotxWyoEDE4QmLf1xBsCpm9SeoQ/eCC+AWWGkF2yRJueaBBOn6M+Z+wNgnf4DiHk62JpQp/JQy/pna7udSbztwsuU4lEMmVG/vjlw9PQVFgkZPvwUHyOOl3G5MFHFJr87JIl3XUfx5Ndfts84kAT6zxDcUmuzkHD1ljJIWHbMdNyLnf2HxKQMSYQLBIQAnAEsoqucvYdjDNxWtk1kx9Y723b3fLZL6hIbIVFiUybUbCgv21j8soISqbcy3FsnI91VHQZ5VMX/YVlkhBsL7PwyvhXop0NdVpp2ezfJ2Ihq/ia3NLYq6BHxZAzu3Qm71hgEpm+bM7DadkzhZ10VFKOMEVC6DOnxlz2KQCOY7tq/zN2erzbEgAAH/WaXmnt2L1ofqZsJJ9Bk2GxJAlb67zW6uEu35AzWyRVRwKmUbPDOqXs+unouiODD0IQEnMHqmDk6lw0mMwYnrr0iQF3c/LsQRKZDg/b40wt1eZMuu9TVc6U+lXLAt1HYqbJKLgi7OtCg+bkFRLkly1Ly5mVLGsQLOIVHyPFeSblCFNcREyY+2j8e343mK1/amz6buHlBYpResYUGR557XWcUEQg5r7mgrh3Kciun8b0e6im8xBsOmn7gzOLF9t79ibLGgCgYOIdvDpwEIzkX/lI6Y/+0bnlmb7dr8aUrSib/XtLx9bklREAAHTGCxmfL8X5JOUIU1wsQBAcf9jx9WbL72vqdiycP0Ez+pgnQ6GCIisOJcFNZgAAIEIUP12AfXoIMOdQ5EubPjHoaU+WNbFEzdDx7jyLB6k8jVeQkSiawrlTf7UJ9/Y2fvgT3Ns75FcYkQgYcEuRIsolH1nmvMUaTTEy5zPo9nqz5bcn67YtvHymPq4ttBxLCwgude4I/2OzeEqhdMmpqVAS9ycet+V74+GwUqkAACRLVwRcZDfQXvWp+cBbBVc/ljFt9NgoFwpuUNDtFBeQOEOspXqEsQmbMI7l0UTglThFIqzrNz9cU79r0fw4vSAA4OKpxKPI716IbaniQqe6WUn0glEgCE6iFwQX2Q3MmnX3xPs+sVV83L7hDzQeGD1DihSjkXKEZwEGfdudln1uKkzHk9xZ6e/d6gh0RnhNzVj2uX0tIQFOlMYYljyHY2sXLR/09D1W17jziu9DiV6KINl66eVl2PrjF7oglyoKY+nkBzZI1Jn1798a6E3dxhSJknKEsVHlyYtuysyYrXNW+3s224M9I0XVAwBkztUX3ZjJsVzfdoflgJuKxLUOMPeqdLFa1L/L1bfdEbHg8RePIVjLfnfvVofrZIDBeXtE3E2GelGOucR6sW90dP21pXXflQvKtQIj8V88yJbNoWp7mV7nhS7IpQqMSIqWPF2y9K+dGx/v2/0Ky5AXukTnCw4wiTWCWZpzVvoF1BsDBfC1hNy1Avviga6I7aiXby6WZG2HvZgzCVtQYpKaI4wDDnibQ8EeVGYQZ8zSweJRWg9kkHbXBsgApStT6UpV8cSbZWnO2xQM9+NiJZIxWydWxTsShdoJf3uYxhiRAjFO18aZkSVZf2ckbMY4FiBiSFOsUBUoYPSkbKcAACAASURBVFFC0n3ndI6QA+BPDU3fWGw7rhh9jeilAnmohdjfpP7zbUJVemJzaekRJg6N+rq3PYd5e0uX/XPUUN3njRhzhBwg/JRUL1wSBHMS7vogQ7DGGVplNm9xKAAAGaRdJ/00yqRPF2KBYzhPYzDYg+pKVWkT1Xzf22AP6mkIKnNkxhlaKO6I5AzJOqv8hJfKnKuXG3mvsfpvkWE6146QxlnCR5J+igwyqAULmlAIhqc8XDxqRiJIuauD/s4wIobG3x+vAgDho1w1AdxLyTRI3pKM+MuJOQlPU4hGGVmaWDtWITfG+5azJBu24KE+lAozsBhS5cm1Y5SIbBRnz+Cs5aCbYzgIhjiWEykQVsxos1RitViqFcGSZI40MBz365O1tf7A1gWXGaU/IB1zjgv933rp1ZMl88cn0ep/myOM4qr7pm/PqzmX/SJn3s9AUudHhRF1hEqFMmzGgz0RGmUgCFIXyvUTeDcWaZRx1wdxNykziI3TdaN+mzEJ9qDe5pBYiWTO0YsUcYmED4YhWGelD3UQmbP1qgKech8c8DaH/B1hXakqbRKPy2cI1lXtxz1k1uVpMgNvFxglTkd4Ec2Bnx/IIE34KcpPEmGGDNI0SlMRhsEYluIABMCQ0QIYwGJILEcQpUiiRBAZLNaIDeUq1IbjHgr3kYSfJgIkHaQ5cGrjVrRZAXEAkcOIAmZIVqqL8QhZmsUcZNiMYy4cc5N0mAEwiPoVlgMsxmBKJC8OQUrST/s7wyETitkJjgUAAs4qUt+nKr0zhlRTTGAJrClWSHQiV6Xf34U6qvwwAs18qnTkXIgMLhjkpxmc9Vr9LAMCPWFXdTBswsb8ODtjlqA1IBzA3ETYjIdMEU99uOypkjuOV4ghaP+VCxUI7w84SrA74qj0l/4k3nsyMu3rLON+kpuEbhwEKe5dFHh5i35GCSQX+J0PwXbErZ4qpK8Qk0B7WBvfkEY8EF5SmpacyxyOceqPNIVzOjc/6WvfO/bWV6Q6IUruLMmyFEfjzPd/UBxLseoihVQXb0+OY7mIFQ/2oKgfE0FhVb48c5ZepOT96g6MEiEy2DhDK5snZOsOS3PuukDEjKmLFIU3ZMTfDxuACtHOKj9Dsplz9NkL+HVnOYZz1QTC/ZhxurZkWXb8GRmcdVT4yCCdszBNok1UVjMeLvke4WO/e2Ljp5upAEMGKTJC0WGWQmkaY85waYM8HCKDRQqRWAWLVSKJSizWiqU6RKaXRDsxNEpHbATupnAfSQVpMkwxOMtxgGMAFaQADCRaEQRDYpVIqhVJtRKZXiQ1SuUGydA+EAecJ/0RM64tVuABCnUQhI9iCZaDAAQAx3IwAkm0IqlBqsyWKrKkisxTlVfEijtO+LIuS1NkDe36sDQb6MKCvZGIGWMwFkAAQACRwMpcuaZEri1WkmHaetCTPT9Nboyr2+RrC7nrApiLAgCI5LBhghqSQLiHKrg2Q0DdZz3p9B6PsAynzJKqChSZc3l8t2SQDvdjmIvgWI6lOVmahCFY+zEvOUHya0nX7DTdv2dME0EC62PUTrSt7VdkycruEVI5DoFjuYrnW3OvMuYtjnfL48j0/uZrSZYq/dHFEnUSWqUVz7Uoi2UFizPVhUkYQD75aodYieQtNgroxwyn+YM+zE3mLkrPmKkddX5hVOre7GJw1jBFK9WK1IUKRZYUgiHAsbYTH1uOrMy/6g+ZM34Spwxe2IE1vt6jyFOkTVAicgQWQ4gERqQILIYQKYxIEaleHOfEgeWQ27TdqcySGadpleViTZrAyWzTNof1iFdmlCiMEnmGTJkr05QoRTz7gh3rLL6WkNQglqjFYqVIpIIlarFEI5JqJdJ0sSSOaZTqv3UAmJMbpSIZDEsRRALBEgSRQGI5AklhsRyBJbBYgYjkIoluqLW2T/sj/ZgyVzbgyQYmbmAEFqlPtQxEEgSRw6cTIDTF9G1ywiJIVShHTleqg9MPRqxEYNHQewKLYfGgxCzLIgpIKh+lSrzkHeH+f1bcsuxmsUIkUYtFGrFUg0jTxDKtRNgyoL7tTipMi9UimV4iM4rl6VKxErEf91EhOudKg0gWV7MuYsXtx30ZM7SoAw+ZcEWGVJ4hUefLRSO+eSzFWg97IRjkLDTEbLgFOiLuuoC6QKEZp5AN62W6TvpxD5W3OB1C4vpiySDdv9OZPkOrLVECAAAHbEe8Eq3IMFngp9u6wVRybQ7hJcNmPHtBvPLIESvuaQjKM6SqPJk8XTpQcVkPeSpDgd8y7Y+PL32kdIywIgEAUAfhqvbLs+S4Cy+4jsdQ8wgFdtb4NXlyCmOzBDXSh9D1aXfa4b3oksVItj5xg71bHSIDkMllgY5I1uVpypyEeofWgx4AQao8mbcppClW8BrXGk64H3NU+nKvSHfXBViay5yjT2TCjArRnV9by+7Oo1E23I9hToIhWZbmVHkyqd7Ru+sZkUwz5uaXJJq4OiK+1rCnLpC9wKDMTbQ/7WsN+1rDIhmAdVDevEzhdlpC/vaIfqIKc5Gog5DqJXlX8hRtPt0cN87UMARH+CkyxNAhikJpWIKM+dHodwZzEdYDHmmaWF+qokmWitAszdERhqVYGmc4mqNxhqM4huIm3FcwpMoNtkdsJ7xSnVg3XkWHWZZjAQCABmT4VGCgaPbo31E7AADAcP5eTJ4hMUzSsFSM5TwMwbHUsKWILKAiMZb3MyTHUoxxtjZj+ig10iXvCM/pHKG/PextDmVdlqbIjKuPReOM9YBHrBRlXa7nNQoR7I54GoI5V6QLqBqoMN2/25U+RaMpERhFjCFY03fOzDk6haAZ+CihUAgOiT31wYLrk+BvPmjreaqh6aP5s27KHiqNHT8RC+6qDRTdmAkgYNrhTIojtB/36ctUUr3YUemTasS6skRn40w7nBmshW4xs8uvdtcGchcJeQcGW9NfJldr1BzDOSr9qA3PWWSQCR2Q9HdEIBhoxyjB6W+B7zTPYDiW69/lij4FhmBdNQHcRejKVLpxAu9h3zZH/pKMwX01juHCZjxkQqV6BA98YTvxUcFVf8yYfls8XUPLAbemWKnmOwEWC8xF2I54DQuU2vSEljfTOGPZ71Fmy9KnCrdDY4z9mFckQzLn8auUBgiZMGeVXz9elTaR96NH7YSz0iczSjPn6PgukCEDVPbliQ6NxjlHmJJhig0Zoro3Wr0tcYtYspyzytfzrZ0M8ZMCpzDatMvpqBKoPOlrC3V9Y6VQ4WpnmJvo+MrCt9jDcfd5ezbbElPk5jiOo1j2yfrG4vXb62zC1Tg5jgv1o71b7QPlMe1wsEzCheO43q3fi+iadjrDZixBg33fOTiKDjy5lqztZSjWtMtpPeQRfBvtFV5P//f3jSYY835Xz2absOdLhmnroTOUh6Pvm69doLhr7zb7Gf+znKcx2L3ZZq/wsjTva0YduL3CO0KCiLO9fvXyprX3437z6OZYrnuTjfALF78dDBmmWj7rRR0CZf8G4+8Md2+0EoGEvlDUgXdvtHqbhWul+dpC3ZtsoX5UQN5gL9r1tdVV6+f1YtM4Y97v6tliS+Ta45RhQl544YVE/O2FxWazbdmy5cEHkx9jEEYgXZkqzsk2AADLcIAFGbN1CM8Fk9aDnux5aUJmdDhg2uEUyZHcRemCZ1yC3RF3fbB4aRYS36jv2SCDtGWfe8yyXGFNzgGsGH7z4WMBgvoQLiufZhRsJ2zGfK3hgiXfT3biHlKsFInkCV0mACDQherGnup5a0uU1oNueYY0zjHzsxiMaMep4Sw9uvaA/Opy7VgVjEDmPS5ZukSs5D1ryFEc6sHV2adKCCOQpkihzJXZjngRGSzR8GtcIxLY1xzWjv1+pEFmkOjL1BErHupFVXm8O0/hflyZI/u+DwcBeYZUX6aCRTAigflu4BErRa6qgL7srMt5xEpDxrTb6Ii7a/NTsFiqypkMRphphoB2jLJvm0NXqoxzfmEEYDEkK0R8tShLsYJXPEaRpUm0JUr7MS/qJAXc8yhipUg/Xo05SdtRr9woFbBwVGaQ6Mepgr2Ys9InS5fwsiDVifUT1DTGWg97IBjEeUNgEaQpUqgLFe4av685rMiUIlLeFd0pPzfaOrsLv8744gRCIF51OiyCeK8qBgAAkLfYKGBFWZScKwyGKcLHTMImDHORhTdkJvjZ0zhj3uvKXiJw4GWAfU7X3D37F2cY32FKx84T7gWDPaivOZR/jXFw/SgzSHBPonuuWZJFxIOMQqDwhkzLPjeNJaqjJC7PR7L0+K56AIAyV1Z8SxavAAsDyDOkhGeoOINYJSq4LkNwHToUCBgma3gthhpAUyQP9caITSGsjgMApE1S+1pDIySAYCTn8l+W37/O07y98eO7MFfnCIlhEZS/JMO00yWgJLFODeUtTif8lOWAO0FTsATOu9ooN0p6NtnIUFyxrmKSNkldtDTL0xj0No10084KBNKnagquy/A0BlEb7/dTU6wovjmLIVh3HY/N+IgUzl5gyF5osJ/wEf5kSmMOJuUIL1kgIKBZNxhVgVxYdTaE/h2uwuszE9mPz3Dc800t91ZUr50769nSMkBwgicGqAgT7EXzh23BTIojDPVjqvwz3AmEQAXXZfRudSQepkdxz0J8azUbQKNm06cJiSEnUiAMluzYe8lbRaAqUIT6kylkoR2rDHSPEvUJACAzFE36n0+Nk29pWnNP/4G3RghDI9GI0qdqbEd4hz45G5lz9Ko8ef/uJDhX7Rhl4Q2ZILGwxrAIyl2Unsi6J1gC5y5KF7yewFCuSZ/K+90WK5H8a4zxb2LhS8oRpkiU4luzhG3yjdIbQa/cf+iox1t9zVWLjOmO476MOcKDUIuVSN5VMTY2SLViMpBoczJsHuoIAQAiBRJt+CdoHM7QShdMwL8+kaCd5CJNE+O+pEUvg0VQzKWAiaDMloVM8ThXKHPmXVN+tQl1ttavvHmECKWqPLlIBvtaBPWZYqEdo0zWZhtYAp+ffXX/baQcYYoLyVdmy9w9+6/OMO5YeHlUZR6WwIJXOY4EBBJfH02jTMxZRlmaRPA8ECyGB+Kny5bNvtgCkCqzZagtmQEeYRHM0slcqZ4+TeNtDMaZWKLOLLv934XXPNG1+anOTU9QEU/MZMaZugQn9oaQ4KxBinNNyhGmuDD4SOrO45V/aWrdecX8FyZNgE+vYkjK5ryYJF61yTOSH+BNpEDo0+GPIZlEtmw2+vmRRAzCEjiJvS5FphR1JNMRqgvl4aSOjkIwpCnmt9ZMP+7qqQ9tEyvT61YudVR/BrgYt+tcPOsUFy0pR5jiArDRYpu8c0+2TFZ1zZVTdedJUElgyLfBFmYmWTgQAJA5RyfRfL86VLpoEhfGqepuwQaN89SJx20ZAJbA2fPjDY8QD7pS1fDh5QQREPgGkSgKr3li4r1r3I1b6z+4LWSpTW6RUlxapBxhbLZ07ggSPCYJXGiiC8P+S3ASxH0V1Y/VN6ydO+v1aZNlQsOH/mAYOmgGQ4q7F6LrjgBa4ErUxJf+D0HYes6zAoEEdU6SiMJYOul/1ubMvb/9q993bXmaCidnvWiKS46UI4zN/Nw5O3r2vXvyw2p7XTzpT1ir36v5aEf3XpyOdxwJpbBVtWsO9R8n+UupRajRV8pdhHxm6p+6c2+OXNa45OorjclZPvDDQzQxD8nSEXsbL3RB/kuA0iffMu0334kUabUrl1qPreaYc7VGP8VFSyrE2kiwHFfjqK9zNinE8pvGXKuWjBILyhQ0HzQdC5HhOTkzZmRNgeII7NQTMB23VAWI4JSMibOzZ4jhuPZQ1zmbKm01AICx+uKZWVNHLdgQCIaUIklekDKyHmFrKPS7k3Vukvxg1oyZ+uQPMP7AYCze8CsbNS/fDSl4z1T9d8owJQXc29u762XM3VV49eNp4+MQfzk73HA9wouJnoApXZ7Gt96IwnJcpe1kmEKvLlzINy/NMnv7DpEMsXTsdbwy9gX6d/buXzpmSbaKX/jWlB5hMrGG7Xt6DxIMeWXB/LH6UcQIWY6tcTTUORtVYuW1xVfqZaPX+yzHNblbqu11OE1MyZg4N2cmAsU1ZmgN249bql2oW4yIZmdPn5T+/aqTEai01TS4mqMBGDOVxrG64iJdQYKu8WyOEGWYV1vb3+3qeWZC2W/HlggWkfhvA/1wH6SQyn9yOd+MKUeYIIHuI727XxZJNUVLnlZmlwszco4coSVkq7LX5qiyZmdPF5DdjXn39x3x4r4ibcFVBfPFCL+dGGEysrNnvyVsvTx3TpwN/QEiFLq794A5ZFtcuGCCgYd+cru364i5QivV3DT2WgF1VMoRJoQH9dojDkvI7sBcHtTrwf0hIshxnC3i1EhUq29842wZURLtCZh6An2WkKMnYOoN9Iph8Sc3vxvPSVnAtrk7dvTsrXe2ihDR+9f/M/4CRyj0pL2u2l7fF+yflTn17vLb48zoiDi7/L09fhPBEAAAimXUEtVdE5ePnAulsP6Q5YwjKKo4rR3vwwMT0su0EtUWq/3h2rqF6emvTSmP7o7gRZjEVJIkL6y4VGADaPBPn2le+Amczm8lSMoRJg7HMa7ar/sPvKkpnFNw1aMC1A2HOEKKpT2YN4AHywxj+ZoKEMEaR0Onr4dm6Vx19pzs6ZlKfuHjCYY8Zqls83TqZNprixalyXkvzG7zdh41V8IQdMOYazIU/CY1rGH73r7DJEPePHaJkU/eBldzpa0mT51zTdEiWKjYckqYNzZBMmyPOJ2oyxywmkOWAB4OkiEAgFR8qq1BUCTBElJYqpGos9QZeeqsYl1hhsKYpUzf1rWHZpmbxlzT7uvuDfSZgxZb2OnDg9SgSQUYgtMV+mxVRpYqXSmV5aoz7y2/Y3gxUBpv83a0uTu7/D0B8tSqHJqhDPI0vUyXrc78+ZSfxnM5Ta6Ww+bKdm8HxVIAABEsYThmQf68+G9IpjIjU5mBQKLNnd8F8KCfCFxfvHjUXDiN28KOwUcwDJOz8iAZ2ty+wx6x//qyF//RafdR1CdzZi1I5ycfQzDkYfOJ/X2HG91t3yz/iFfemLxy/M0Ihb648KnETbEc99NNv1x787t8W9Mxafd1/7PinXeWvDJ8AADWKmTXTME2HFc+eG2c1nCaenzfsy/OeTLxgkX5y6HXnrjs93JRcpR+3635+L7y25XiJAglAgC+at10S+kNSRnh7/b1BajgOP2YgbJBEJIx/fb08qXW4x/Wf/Bj4+RluQseFCtGXz3bFzD7Sb874nWi7gAaFIvFMARzgEMgJEOZHv+wHsGQja6WRlcLThMaqXpG1pRFBZfz6oGB00NTJx31AICrCuZfWTCfV3YAAMmQRy2VrZ6O8YbSe8vvEMH8lra1eTuPWSq1Us1tZUtlcb9FLMcdt1ZW2+tmZk39+ZS7+ZZZGD8cRxgkw13+HlOg34N5vZg/gIcJjgAAEBQ5sBqF4RidXJshN6TJdQZ52ry82RkKY4m2SATDQ0zZI86oq2t0tfrxoBvzRig0XW4Qw6Iq20mjIj1blZGnyV2Qf/nw7AAAN+Zd37p5Vta0WROn2cKOCtvJDm9PX7A/hIejCWAI5Kizy43jfz7l7oHPg+W4bzt3EAz50PT7Y7aAaJZucLfU2OvafT0YieM0nqEwzsqZ8tNJyzUS1Z7eg5aw7Z5Jt8fZeiJZcnvX7v19xzAay9fk3D/5p0fNFTOypkw2Thg1b5pcP+S76nP1r2xZ40P9JcYZQW3er+u6/jxh/M+LC3mNhUa/HIqhDIo0a8hx36QYbQi+NLvbO/094/TCRQ0H0xcwAQisrlv70Iz7+VZMw5EhUg/q+UfFv/+n/M6sYc186Q3Tg0+sZXqdSFFcPQAJIrKEbG/Wr/rJxB+NN5QmWDYAQFeg99lDf7+j7NY5OTMSt9bhaf/jnmd/NO6mJcVXxTOAPzK7evbt6j1wWc7sRQWXl+gKEzEVocJ/OvC36RnlY/TFAwHlNBJNliojq/z60sk3+098XPvO9Vmz78mZ93NEOlJve3ffgc0d2/PVefeW3zapYLzgrvk/TrxdaavNVedoJKqZWZPTZWkCXrZHd//ZHLLmqLMgAHd6e3I02cWagvHppTGrrOGQDLlsw31Zygy1RN3i7vimbZtSqtBLdQa5Nk1uyJSnZ6szspTZMlHstshdmx/iAJupyKRZ6qDpKACwVCxRi5UKsVyGyPQynUqikIsVaXKdVqxWS9VGhQEAcMR84qWjK3LVmVqJttnVvrFjOwBAikhliASBRGqpCgCgkarEkFgulsrFcgjA6Yo0AIBOqpMhEqlImhbHVNRwLvmh0Ye3PD1z/iwRDOtlujR5mlFhyFAacxQZOeosFf+p4LerVrd5u9QSpVFpyFfn5Kpy5BL5MXPlgvy5k40T47HActyO7j1uzPuTCcu2du7cbzpmUOjH6AonGcePTys720sDALCG7V+1brppzLVj9SUxE1RYT37WvL5YXzwve+bMrGmDX2WKoT5r/nq8YezcnJlxXqkH9b507F/z8+bdXLpEAktYjl1dt3Zx4cJRZ0DPxtN7/nrb5Dvf67V/YXb/prT0TxPK1KJ4m1ku1L3fdNSJuielly3ImyeCkTeqVxWqc+flzhruHngRJEKfNW+QIlIOsPeV38m3STucbV27bRHnnJzpjc6Wn442gDwqfYH+bd17pmdMavN2TzCUDvc3xN5Gqrpb9fgtcRp8q+oDnVidrc00h6x3TlguEyW0K/yD2s9ojp6cMaHGXn93+W06aUI7Pj9tWu/B/NeXXPVd997FhQvLjeMTsba379ARS8UfZz9Uaatt83TmqrOuLlokuPP6WfOG/pDlR2NvHHd66DJIhuxhpyPitEdcS8cugSMe88G3fR0HsufdnzXrHkRy1n7tof7j1pC90989WTfhlok3CCsPAKDN07nfdOTGsdcc7j9R62gsM5T8fMo9fI00uJoPmo7dMeFWMSxqcnd0+bpNQbMb82Qo0p+5/I+jZicY8tvOHRRLLx93kwSRuFCPPeK0ReyuiNuN+/2YP0AEaJYVw8grV/1liHOlWWZnzz5b2LG87KboOglH2BWhIgEq5MX8ERJFKdSH+1Eax2ksSIRJhgKApViGZKh8be7CvLnRprYL9dAsjVFYgApBADhRNwAgREQohiIZMkRFAAABPMABDqdIgiNYlouQEZVEidG4CIYBgJeWXH1NyVWjXKpgnaeLgXOnR8hxHEZhX7Zs2ti+jWbjVfvr8Ha/VbWq29/H60Qsx27t3PVR/TqSESK7ZQ87X694zxqyj570LJA0+XbVanPQKthCkKKeq6lL3/TtFd995sB5SPQRNLGq9pON7dsCxFCltFW1nwguTxSGZVdUrgyTEY7jjlkq653NCRrkOG517droHycs1Vs6vkvQWo/ftK/vcPTvXT37P25Yx7DMGSloJvDkWqqpP06D/6n7LBQKcRznRr1vV39Q42hIpHj/qfss+keYjHxY/9mWjh2JWNvZs88UMHMcx3Lsvr7Dq2o/8aAjqQmOTAAPftGyceBfU8D8ScOXq2vXtnk6BVjDaWJlzcejJkNdXe1fP1r5z8ssR1cx5FmV+Xb27Nvbeyj6IBLBh/tfr3iv129KxAhOE2sbv/q2cycrVOXSGXG9X7tmR/deAXmDROjjhnVrG78iaIJXxipb7YrK9+qdTQJOOpg49QhTjjA2/UHL+zUfezF/nOlJhvqo/vMtHTsYlt/bZg87VlSubPV08C8jx3HcEXPFypqPhXnQKCiFrahc6Yq4R08aCz9JvtjUYty09Y5DR5879p/h/kwYJE2uafgiQSNrGr7oOV2JYBT+SeNXCZfre0fIcdz2rj0V1pOJWOv29w04Qo7j+gLmFZXvuc90D8Tx9sDzX8RZiQ04wij7+46srPkYowSqBw84wih1jsa3q1bbw05h1uocjVW22oF/MQr7vPnrtY1fkbRALdz3a9cMOULS5J7eg+/XrqEY3lLVO7r3xVntos6OtvWPVP7rcsuR92kiHDPNxrZt+zoP8S3DcGiW/qThy4OmownaaXS1vFW1SvCz4ziu2lb3RuX7PYK8sj3sfL92zZaO73hVj9EG0z9PvNPl6xVw0igpR3heoRjajwcEZNzUvl1wRfBJ41eDq1EBeDH/a8ffFlbyAEm93NJm2Pjt7UdPtAZDn9dtaHS1JFKYwRy3VCXYGDxirhhycxLvYmIUvvZMb7qm4YsOb5dgg12+3v19RwYfwWni/ZqPK6013x9iucBzX5CVcXV0hjhCjuNcEffbVauF3cw1DV8MaWPhNPFxw7rNHd8J6F7Ywo5tnbuGHOwPWt6u/qDZ3SageB/Vr8N59jNGgOXYFZUr46+pI8729m/+t/Ifc03736TQoS1mlmU/qvm8ztGYlLLt6T34Uf06vo3sIRA08UnDl1+3fSvYDsXQG9u3ra5dGzl7b3gEWtztb1et5jtKQTH0lo4d75780IV6BJw05Qh/+CTY/YqQ6IrK9wR0F1w48Xxjs3HT1ntPVLWHQhzHtbo71tV/nUhhhvBB3dr4R6SHYw5aP6pfN+TgZ00bErxjtY7GM1wUx7Ec++7JDx0RlzCDnb6eA7Ea+9s6dw1uepP1fYGnP+WY0euv4Y4wSqtbyJDDxvZtXsw3/Hinr4fvSBfHcRRDf9ww9KFEEWCN47gae/2Qx5EgTa7WHd37eGXBvH2dW56peG12z86/EYHvJxdYlg2FQh/VrxM82DOEvkD/29UfJD7i0uxue7Pq/eh8gTBcqGd1rcDPM9rJE9B2jJDoVy2bh04cxEGcjjAVYu0SRiMRrq4JAFCI5Y/MejD+Zc0AgI5w+OGa+vHf7XISRNU1V66ZM7NUpQqTkd29B24oujqRwgyB40CcIQWGQzLkV62b75r04yHHZ2ZNrbE3JFKqVk/HkH1gEIAemHL3580bcFqIoDzHcTFXA94w5poibf7Av+LJXIZOKgAAIABJREFUBZBaTh5vF3CKKAK2rwEA1BJVzIi7Y3RFEv77FkQwQrOxA6gKsAYAmGSc0ORuFZDxbExML+v29/J6lDJ9wZilL019cAsEIXXv39q56QnU0Tbw632T7zhoOtoX6E+8bAWavPsn33nEXJGgnQmGcb+Z8XO5SPj23HR52gNT7xb2eUIAurJg/tnWA47A/7d33vFRVdkDv++9mTe9JTNJJpPeQyiBBJDekSrNhkqRVdRdXddllXXdotj2t+rq/mw/3UVcQECkE6QTQkiQQEiAUEJCepuZTKb39979/TEYYuo0QrvfP/KZubn3zJl5791zy7nn8Nm8h9Pm+n2asE+QIUT0DQTgiFoz9+SpcbknJGzWhelTvhiWGfPz8XkX7Vo26PHAzxK0U22ojZPG+N28zWFYOvDRrsHqkmQJlfrqQBSzuKxdo1KxCfazQ5aycH+OFUIAMe8OEvAWjrTvLAJ0sLPP94qYFJlcQctPG3TYOMvNUMGV+XDq3B3X9vnaihSFx059bdhLx/hhKVe2PHv5u6f1FccBZDCA/WrIU5d1/o9gOiJg82cmBGG4SWBE4MdX7jHunXOEiFuBk2G+r2/4sLzCxTAvJCZ8P2oEv0u+CE+gCrMvyTp655z6wvT4vtyde6anExc4hkFwSw4L8dl+jq8hhF52SazUSCJM7Dx5lTPBq2M8QUHEEbba2vrt4/xAxpXq7PpQ30Ol9IScH0pghMVlFZICX9sSHGHkqGeUI5bpLu9vzP/MZTNGjlwalrkoKNYLcUtBhhDRPc0Ox1fXq7+8Xj1YKnl3YMacyIh+G0MuSJlzi0asj6bP87stBHB8zKggKgMAEJICyus5DXfBSOsXBzljUgGrx1WpcIGChn7mb+qKjCttNDcHSxoAwMuY8t7zQGRWjbEuiIYQAPBY+vxAmmMEWz7oodCBc7WVp4wXf2g48Zk8Y3Z41mJ+mA8BNhH9zF1/oL5/gm7fP7gZZl+zel1NbUGrbmlczItJCQkCr4bGvWefQAQFy0d72UPjOZN7iwSNYo3eCcCfY426zGr1ua2akq0cqSo8a3Fo+gw8sCgHCJ9AsUb9h7GZzce2cRIHcdOygBdTE8ZidNWVc1KHYcRd/HteMBrXVddtqqtPE4uejov9bmS20OvQMIj+gTt/hPXzA5zx6b1MChF3FKQoPHrCS1Hjfq2vyFUXb6k99L580LywzEVognhHgXq6bsD5Ismcp131FaaD3wEM52dPYoUqe6svlGBcgfnQJgAwbloWGZfujfl0t9TainMJSShvwEgixLdAYtBpxzjBSctgcLu31jeur62rsdqeio0umDwhSejz7giif2AlhhORMufJq5yJGbdbF4QPYDgRkjo1JHWqQ1+vKd12ZfOzpCBUkblIPnAOixtQ4Lr7CIYBAAAvoqT6AVoa7QPGYbWX5lPaRnZELC9zPMbu1c+bYZyV550VFyCA/MxxbFXfgZ4Zi9Fx5QylawEYzkkewokf4I0RtRYdpnUtADKEVEEmZLDDY7xp9YvPhfCYRru+tj6nuXlqWNiS2JhZynAigJ05tDTaP1DXW6yfH5T846meJoVoafROAPaejxAyhupC7fkdhsoTkoSxiiELpAljsYAD4fqgntsFAOijN+u5rb3sFKBpfnbfaWo6QWkbbeeOE5JQwQMzvG/F2C22oiO0SSecsJAQ+7YfjPIRBhlXfYXj/EnGZuYMGMEb2EeeI+i02y8UuNX1hDiEk5rFDu87nxl0u5zXzrlqyyFNcRIyOKlZGKtvj3za1Oauv+ZqqgY0jbHYbGUsmTgI5/Y4paMhLGjVfV+Uv8MOY3HmSQ58RC6VyRS4JIQlVQQyy0SGsN+wfLCbfCCFHNd9khBkCO8E+jCEP0M5TLpL+7QXdjvaakLSH5QPnCOOzgK9n5aDELoc/j2qlK7ZcaWYNmgxNil4YAYh8SU/GoTO6svOayUAMpzULE6CL2sSDOO4UuSsusySK/nDJnqvPNXabC/Jg5RbMPJBX5fNfv5kZAh9h1LXutWNdGsjpVNTJh20mW/clAwNCBak3YzFxB8yVjx7eeeWDONqqnLXXXM119DaRs+AC0BI6dVsZbx85Zq+PphyVpc5ys+5G6ugy07p1Cx5pOLFf3ivOeNy2H/abz17nNLUi2YtE43/hXukk2GOabQ7G5t2NTZH83kLVJGPRKlSRULodtFGHW3S0YZW2tRGt9TZr5Vw4jNClrzm/UcDACDlNjXWcF1WSq91a5sdpccjXv0SkAE5BdB6rWn/BtkTfcfI7xP7xQJCIidjUgMXBWjaduEkf+iEIIgCgG5rATiLkPqW6ZS62mj95pjk708B/JczeJqmnTY7gyFDeNvx0hC24zI1664e0l3e7zQ0hqY/GDpgpih6GAAYYBiqrcXdUkep66HbCSADMJyTkMFJ8TZDPXS7XNWXnNVXAGQIcQh3wHBCqvDpu7hb6hyXfmJsZk5CBjd9OPBl5kobdfbSfFqv4Q4Y7r3OAABn1SXH5SJCEioYOR0j/c+IiZxluoGxWdzN193N9YxZR7WqGasRYNgNowUAdDtxvoglU7DkkZz0LL5UQUb9HI8DQtu541Rrk2jiQtpisp49SjVcd6vrGJsFY5MYm4QUhXMFrNBwMjaVM+UxljTU3VJrLfxR+thv2eHdnA13NVS6rpU4q68ydjMAANIUKySCjB8gHDPXeuaISJXAzRjZ99exmGylJxxXzjAWI8AwTmw6J3WYeMZT3AHDPRXsNH1Erf2hoTGnuTlBIJijjDg5aXyK6ObDibFJllyJCyXO8mJnZRlgkZy4dNniV/r8aHdLnb3kOLhxiB4Cgk3zREAZC90u58UCMiY1ECsIXQ5L/l77uVzcRwvRgzhoyvmWTBoUFEPobqo2bP1fTmy6f+PTTthK8y3Hd4Wt+l+fxuasNBUu4bvOXidH/CJejP1asX7jh8Ln3gdBMoRNqxcqXvqAHRWcVI7Nby4NXfIqmTgoKNJa3nk6ZOkfg3JNjbu/dre2iKc8QsakBrgF1fbNW4DgsFXxjN1K4SzI5WIEy9OP4zwhxhNw07pPlEaKlcoRy5Qjltlbr7eW5ZRvfA6DUKwYKJKliWNHsCJiuCmZvtoD3fr3gctNKGN5qcPE0x7zyYABAOi2VuOe/8M4fE5SpnDcPMzHJ9p09Hu6tYWtjOOPmIrzvL0hod1iOXOU0Ws4KUMls5f7uuPjN/fUjJCxWai2FndLLa1tYMwGSq/1GDnodmFsEjA0xuGxZApcJCUUUeyIWDIyoaf7nnE53PXl7uZ6urXJ2Xid1jTgfBFGcjGcIELCSVU8ERbFiUvHhd0lgWRoS/5eAKBw3DyP/J7MHn/waFx8M+21u6XOWrhPNOXRXrpFxtRmO3vUUVkGXXYAIS9jBP+BmThfCJ1244/rBaNmsiNi2lyunOaWnKaWQ2rNQIn4kSjVI1GqSF43T5G97JT1ZA50OnhZk/jZk00530geesar5w3CTveoUaeldn8FGIqtShSOn4cLxH0L6U6s/cJJV205KzrF9tNB3oBs4YQF/sjpgLVgn+3MEXZMinTB84E/V5aTOfaig+yYNPGc5b0sQXur2+mDlrxd3LQs3tAJZLQPqXTd52vt206J1zzeMZ6Pq65cv+VjPHGwMDmTN3h0gLoBADQf/IYVlUhGpwjHzglcmm7tGsbt5MRniKY+Grh/te7rv0LaxY5KFoye1bsvW5/QbRrtV3/mxKezFFHQZSckcm7GSN+WDX/G2VBp2PovQNOShb+mwuMEJBtSbgAZxmH1VPBSVVdtuXbHB1aoszqb3MApS5siz5gtSRyL+xKLznpij7X4KGCTGIQAAFwo5SQN4g4azfJuRkhbjG3fvgcYChAswDCeySjAcUIcygpXsSOTOHGp3XeAAAAANP96BTodGE94M3bSz7YG4/BxkZQQh7BkoSxpOKGIZIUqPV2lJX+3+cgWQizHSA7wnDr1HLTFcIDhADIAMhjJxflinMfHuEKCL8LEUpZIhgnEuFDGkna+avfL0mjNJ38YPyIbYBhgaIwrZElDcFk4OzyGCI0klTG+ju/027+gmqoBAIDFYocoifAYxqAmQpXCMXO8FOVurrGe2i8cM4cVHm3J320vzQcYToQqOYmDeGnDOpq9TtiKc2mjTjRxYU8f5Cw/Zzr4HcYT8gaO5mVNwDuYK9qoMx/53jh+UY7RurOx6YxePz08fIFKOVsZIenhDmBMba3fvM2JTxc9+BTO5UO3y7j73+JZy3C+n5OJ5k9+HzLnaVwkcVVeFIyZ7YcEZ0WpvfQkf/gUMi5d9807wsmLGLOBNyigM+y0UWc7c8StqecNHksIRGR8oM6Wpv0bGKtROGGhJX+3dP5KX0fZnTDnbgcYYMkiKF0zOzyKm9HH3vNNIDD9dQvvkVHswTeTs7uqL7saq+zqRmHqEKqlVjT5kQDnN4Z93zJtGsGomY4rReIHn/J1TtAJ04GN7qYayexl5hO7RJMfDtB6mQ5sdDdWhzy1ynr2GGPSCycu8H7a0RXj3rVUm1Y0aSEZk0Lpmp0V52lDK4CQkziQkzTYp6tsLfyRkMrNJ3OI9OEh4+b6rRKla7Gc2CWZucSQu7n10o92wuSkDJLEsSHJkyWJY9n8HnuSjjAWg+nQZsHoWeyIWErb6LhY6Ki8CJ02IiQ85MlXvZHgqrliKzkhmriAkIUB8Ms9IJ0auuwAMgBnKV54r+vNRrU2WfL3cNOyuenZv9TKRLU20jqNu62ZMepok56xmW7+GzLc1KGM3Sac/DAh6sY1hrGYGKuethgofSu0Whi7mbabocXM2C3Q5QAYDgAEnqi2OAEhxn9gmjC7r+A+vgbzvqO4tYl5y07pt31O6b1OLEBT5rxd5uM7IO1biHTabjHs/rfjuj8ZW7QO55bzxb/avin1x4Py3TnLis7uamyyUb4Fhmcot377F5TRnywn7ZhMJgihfudXDOVzckS3psGQs85WcqJjoa0039VUHYhKEELDrq8ZlxNCCGnK+GPfmVf7pF2IW11v3B9oXifj/g3w55w41qLDlpM53rd1Fpab3vtFxg9HxQVHxXlP9gm3pkG/7XPK5H/m2xvqQQghpM16w86v3NrGoEhj3C7T4S3Wc8cDkWY6vOXGlYWQthhNR7aac7czbj8zmlmLc10NnRNdMQ6b7UKBrdTHtIIMo9/xJW23Bp6Yl2pT67d/0f41XVad+tzWq1t/XfSPrAv/XlCX+7GprpjpM/MiTZuObbOdy/NbDcblNOduN5/cC/3K32QvO6Xf/gWlU/vUiraajQc3dbzK/oHSMAWEq7nWfuWs9/UZp12/4//86CmcNVcMu76mrT5kV7G4qcMt6tUXyrIOHxNt2zlp5/a/X756tk3vZ5oxhjHkrHO3NvvTtgMmk8l28ZRPP5oH++Uic/7erubTdPQHxulnRlkP1nPHHeU3E+ca929gnI5ABFKG1o62ylF5wXJqfyACO5lSR3mJcf8GbwdSNGP4w3p35c0L5yg/56wqa+9/GYfNsPMrZ7W/SSJp2njguw5vKdOhzbbSEz036INOX9Z+5axhz3/8vsTWc8ddLbUdS24Op3x/EBiXM/BhTTu02WDM+TZwQwghpIxt+h8+Yxy/yP/HMJSl6WJDwVcX1z12+u+ZVzavbCne4jD01vnYL5027P3G74EChNDVcF2//Qu3psGPtozLaTr6g+nwFl8VcGsaDLu+thYd8c8GQ68NIfHmm296M0G+M2lubt67d+9zzz0XdMmEUMKSR3pfHyNY3PRsnO/z+QFKUy8YMxtj97HoREFYYjBuqK176/LVl0vPlxqMCULBUrv6k6jQ5yY+OFYhj+Rxvcxj0AnTwe/4Q8Z069HjE067jS7NE47xeTOJpVCRMSlYl3UVZ/k5buowv/VhbGbHxVOCUTePK+ECsfP6RXZkvN8yneXFbFVi+3INKyScaq6hja0shcpPgZUXOEmD29+yQiMISajp0CZOwsC+D89gGIZh7lPXyJE3NhcpTQPG4dE8MUmSAACMxeamZTmvlThrrpAxPscxgQztrr3KSfg5nBuGcxIHUq3N9nPHyfgBXa9Xn3T+svJIUpVgOvAdIZIRPW8Z9Kge5Wb0GlbYzYNJuEDMTclkLEbochCiHveuugUjCGd5CZmQEZTDfBjJZWjKVV/BC9jPCOfwyJgU04/ryQ63BIbhpChMHJ0Vlvlw2NCHcRbHWF1Ye/QD7YWdNk0F7bKy+DLil0HDWQoVOyzKtH8DKzzKj24KAECIZZyUofZzea7qy2RMqk/b7RhBcOIHEOIQ8+EtAACWwtuuFReIuWlZjM1kydvl533isXNdUgV04v7yGr0D6cWlmIaw1GA8otacbNWdbNUlCgVTw8NWpyaPkT/AIwgAAHQn+3ckth3Lid3ctGxvDv73ibvooGTUzMDlBAvzsW2iyY90LGEr42xnj4Es//NauJtreYPGdCzhD59qOvgdIQtjK+P8FtsRlkIlmva49dR+4cSFfVYmx6fbd59hNEY8TAIAAAzdtR/nj5jmrCqjTW0+dyIM07Wz4w18gB0e7aq5wgmG8yculErnr3RcLfYjhRVLrrRVXepa3tHW+gR30CjHpZ94Q8b517yztLQs667/0Aatr2cVuoILpeLZy0w568Qzl3T1QWML5IrB8xWD5wPIWNVXTbVFukv7qve/xeJLJbEjRDHDJbEjSXEEAICQKiTzV5oPbyHj0ntyXu0djGAJx89zN1bZSvL4vj9HLHmkdMHzjks/3fBe9BpOciYnaYirNpi5JzvrdutEI/yAgrDMaDqu1R7TaE9odXEC/uQwxXOJ8ZseGC7qEvkzQCsIABCMmhm4EAAAYzFAl9PviVHQcVZeIKOTujr+EFJ5QH0TZLp6BIinP2E+9kOwDCEAgBDJvLGCAACMw+ZMzHAcusB/ahwAANI06M4b8+aszicYulsnEZZCFcwLjWGdPCm8BOcJGbslaGoAQMakGC8UBMsQAgA4ExeZj2+Tzns2cF9lnCcUz1luOvCddP7KHithuCBigCBigHLkcgCgTVNhqj2tLz9ae/jvBMkXx44Qx4wQRQ8Vz3iSsQaUMY2tSmCrfM6s244PHmEdwTAyrvsIEkEBGcLbDAXhJaOpWG8o1huK9foykymGzx8vlz8VE7M2e5iCc2sD1QfFCgIAqDYN+UBQp4MME5BDJoTd9mj8YROtpw+JJj/sj0i3q/sVbAwTTXnUD4FBgTN1kOlPm3jzh2NCLqSpIIbpgpDxY/3zroYQyWhDq6/xDXoCY5OC4VOsp/YLRs8KXBrOFfRmBbt8OD8shR+WEjF8CQDArq001Z0xVOXXn/hf2mERRg4SqgYLIwcJIgeTwkAnrPcGyBD2NxSE5Wbzz5bPUKI3SNjsLJk0SyZ9Iz1tjDwkhAyOcepPyJgUpzmYqcxpq5EdwLSDkzyk23JcIOYk+bmm526pIWPT/FbpFoFLBezMeGfeZe7sYaCHGaGf0HQfsb7uOfhZE61nj4m8m457A1uVyAp49z1weIokniIpPGsxAIB2mm2aa6b6YvW5rZacP2MYLlAOFCgHCpUZougsFu8+jQCODOEtpxfLtzo15S61fLcaQiTjDR1/KyT7HYuEjA5+3hzByOmBC+HOyLR8nMOdkUnGpRFiGXB5m+m3dzCSS8YHczGKjA1GiLuOAn33AOodXCgVjAjCFemINxGD+xOCIxJFZ4mis8BoAABw6OstTRcsTRcaC/9tU68iJUph5CBBRAZfkcwPS2EL/IkqcDeCDGE36JyAxIHI3xsYWT6El9w4pBygkBg5rhC7iqtuRFxzBWfnDGOTwbX93PThQZQGAOAOGBFcgQAAvwNK3KVwZdFcWbQ8YzYAADK0XVtpabpgbbncdvWQTVOOYYRniZWnSOGHJfMVyQTn3vx9kCHsBhcN/u8KY3XDCUp8qgoj+trqLtIy/71ukvKNZsZ4Tm84pzdIO1i+sfJQGdmNUTW5gfjOGiwi7lY40wY7D1/oFHoUgfAJDCf44an88JsTd8phtGsrbdpKu/aa9sIOm/oqQQp4imS+IsnzVxAxAGcHJzHq7QUZwm5Q8sEbmTgDQaEavl1C0xA8qMLHRtywhzqXq9JirbRYrlusFRZLudlyyWiKE/CjnTKckcSwlC8PlcyLJcm+tldKdfBwIwMhSBRjUyKxGKG3rmUMBHoXCL21bjSIuwlyWIJ900m6RkPEBWGKiUB4YHElN9ZRbwAd+ga79ppNW2mq+anlzAZHWx1HouSHpXBlsRxZjGd+SUqUGNab01azDSj5PitzogWmSrDwW2N27+5Yo4WFhcuXL7927dotkq92OCstlism65Fm8yWTVe+2WRgLBkCSUJgkFCQKBUlCYapIOEgiFv58toGG4JQaHm2CDhoOk2Ozo3F+X4ONKjM82QKbbcDJgHQpmByJ927kbBT4Tzmjc9y4cCoBliHDBkgx2e0zjVar9fjx47Nn+xNiFBEUHDnFjMZIPZxdWFg4Y4YPWU8RtwK9Xn/27Nlp06bdbkWCzxUD3F8PQ7lgWTIOGcquq7ZrKxxtdQ5DvaOtzmmod1taSYmSK4vhSKO5ITFcaTRHFs2VxTS7eVuroNYBR4djc2O89cPSO8HGSqbRBsdF4DOjMNzHoyharfbq1avjxvVxKuY2GMLc3NyDBw+2v3399dclks6uSs3Nzf/85z8bGxsnTpz4zDPP4D24cW/cuPG5556zWq2Ba6V3uaus1iqr9ZLRdNlkrrJaKywWHMPCSQEf5wNG4KL4kOE1mflPJgg/G92Hk/oFPTjayBxsYEp1YFIktnmSV07tDARFGvj5Fea0Fo4Jx9aN96pVoxVeNoAyPTS6oMkFftIyb2ezp/Qc0NhJgzUltIB1c8mXQ4B2a91oA2kSuDjRNy/8wsLC3//+9z/99BMAgGLAzlr6kfgg+PHXmEFcMHL90gD0X/Lv2wQ0O4yrN16YF/eX997Oy8u73erc7+zfv//jjz8+dOjQ7VbkJmY3ONcKi1uh3gUBAE8m4mlSb62KZ3yf2wwtbpgoxh6KxSN6nplBhnIam52Geoe+3qmvt+rrNep63FgNcBY/JFoUGv2zaYzmSKO5UlVPzsnFrXBvHYNj2NIkLE7k51nMXbt2rVu3bvfu3b1Xuw1Lo4WFhXl5efPnz/e87Wrk3G73hAkTpkyZsmjRorfeequlpeWvf/1rEBXQu9yXTDesXZXFWmW1XjFZMAwTE3wSCBiGz8PkIaz4QWwhZNgJPCxOBFIl2MAQ/LsKelo2Pl31i0tioUBxK3OkERZrgY2GAAA7BVR8bGQYNiQUTIrA/zCkj7FPiY7ZUQN/0gCLGwIAlDwwUIr1aWvbUQkwMwW2VTPlRuiggJiNjwvvrT6HAO9m3xBupYCLvlF+upX521m6yYptneqz1WAAZlGkf3SRMbjg8Wamyow94n8gMwAAsFPgyVy62sqUzA/CPmrK99THDxAPxQYht9mGCvrTy0zRvODs7j5xjM4IgW9kBuExxETcipiY8gtBO/CgsYPfFtJbpgRtCPFCAf3lmOBIgwC8X0r/KTM40r6/Tj8US/CC0RfmtcARcixwUTUW4KahyQ2MLmBxQwsFLG5gcAGLG7JxbFAImB/b94W2uEGpDha3wmY7BAAIWFhmKFiSjCu8Tmuoc4JjTcwlPbRTYGwEtnoI3ueODwAAw1lcWTRbGn2GhLkMww3BHp2GpUowl0Xr1Nc79HUOfb25vlh7fqfDUE87TJ75IilUsIVhpFBO8cPy9CFX3GFDohV/ziRZgd3RXs70bs8e4dChQ1evXt3Tf3fv3k0QxBdffIFhmEqlmjt37urVqzm+Hy2nIKyz2aos1iqrrcpqvWq0XjFbq61mDMO5GJ8DBBwgFLMi+LhwilCQJGENC8UyZGBoaDc//LZq5ocq+q/DiEoT84/z8KIe6hzARkMnDfgsbEgoGBaKvZyBy3++wzR28G4p/VgCMTq8m863VAe219Aey+dmQLoUezge+9tQnIWDTdeZVgd4KcOrBYDdtcx/ymGrA4ZwsN9lYDIuvqeWeXMY4f3qgYAFBCxwooVZcw6ycLAkiUiSYKPCvGpPQ3DVAAvUsMoMGzUqlyji6RT8xUJaycNezgjo5r1mhJ9eYmoszOzoIHTrpTrIJUB+C/NQbBD6zSYbZqXAt9eY5SlB0E3BA9uqQZyQeTIpCNIqszKydhz7MDk4C9RtTpjbwvz9PLZ6iK/LUd3z/XVGxAbvZRMBdm0AAAjB++cZGwXeyAyCAdtaA/5STC1PwZ9Owf3Yu+rIiwWUg8YeS8RqzAlVGU9uus6kS7F0Kcb18dab+iNFMfDRBHxWNK4SYBISCNmYkAWEvgzA4r93yzggS46/NAAbHe7zj76lkn62gEmTgGgBPjoCS5Z4ZQU9NFtB2nYqWgDCeVisCO6qAUNC4Qi5IiRaIYr+RQBhxm136OudhgaXReu2aPaVXDYZjyth6zhaI8jXFbClkBfCEYeLJXKRJIwtVJBCBSkKYwsVpCgMZ/mfub4Tt8cQnjt37uWXX1apVEuWLFEqO6/inT59ety4cZ4Q0iNHjrRarZWVlRkZvWWSczNMvd1eZbGWGW1n2ixlemuT09pGWQjIFhIiLsYjGIGCo8yWCJ6PFg6Ts8aE4X0+jbUWkN/C5LcwR5uAkA15BHa8mUoQYYNk2DNp2ISIHtsfaIC5Tcy72UT7XdtsAztrmCONsM0F+QTGY4MpSuyHKbi0wzEKJw3eL2FGhWFPJPbW7bgY8J+rTE4dNLlhhgz7bDQRKwQAgBMt8GADXJPl2wO3u5Z5r5QJ52FbJhPNNnioEc6I8qrTq7PAteXMUDn2cDwewgGF7obymvz5h6mH4/AWO5jnxXC1J3bVMiWtcIoKs1N9XyNv2FDJKHggXoRdN8FEccCJeSkYysGMLvCTBj7g3YihF6RMcrlZAAAPlElEQVQk4OCAjYP/VjDLkgP9tlUKZRKBDbe5/lpM+zQe6haNA4wKw3EMvnGGfjOL8L4T7BY7BWZE42o7/P1pek0WIQ3sABGOgYdisGsm8JdienEiniUP6Kv+fiD+filjdIFdtUylCT4Sj/t9ZffPYL1ZTO+shstJnfry5mz50jI9PNgArRQkMDA6vPN6Uk+ULWK9fIp20ODlQvqBcOxfDxBc37vqhsXs18/Qo8Lx/1Ywq05TAIBR4djLGTd6jD55PIkYpsD/eZFZkoyf18F3S+h6KwQAuBkQzsWmqrBFcXh4D+MGpQBce4T1wQX6wSg8SYQVaJhDjfDrK7SDvjF/4BCAT2DRQpAo4owMTxqVlCLDAQBgxXiwrZop0sJnkgkrw9QbHTUt2la9xm3WcOo1Ipea574ocGoktEbi0rCgy0qGOTlyFlfCk4SJJGFKebhA7LGUYaRIAYC31/GW7BHabDaTydSpEMOw8PBwAMCmTZsuX76sVCoLCwt//PHHoqKi5ORf5OZesmRJVFTU+++/73kbFRX17bffTp06tesHffTRR69eM2JDBkMBCTAMuDG2C+db7UK9VtZcIWu8yqIcPmmujp3YGjnSyQ8FAGO7LaRdzwA8ufRrltvmpYTm+Klsl1neeBoAoA8f1Jgy38WRsNw2mbo0vDaPtOu6bQUxoiZjsbLqINem7UmyTay6nvmMmy2QN56OurYXZ1w3/yWMbIvMjrq2x/tvSrH4l8a8Tjr1yWe/YFEOCLDajMWxlzZjwJ/7wWQylY5/c2BzrrT1ckv8lMjKH/0QAgBoiZvMdllCm4rKxvxpwOl/tsRN9luUB7MskeKIm+OnpZ75VBM7Xnn9YN9tegHDGhNnmUJTkou/akidF3N1O067+m7VM41Js90cqURbRpF8lssq01wITNqsGW2tAnboYdc1c2hqgD+dPmwwi7LVpy5MuPBfdcyE2CtbA5HmJkX6iExN7MS00x/XpS6Iu/x9gD9dU9IsXeTwjPx3mpNm8k0NMnWp36IYnK2Om9QaNSq5+GvSrtVEj7OLIqMq97EdBj+kNaTMC6/LKxnxGr7v3WyR/+4LLl6oNmq0qmJvQ9IcdfwUVcXeiJpjvgqBGF474PHIqoOkXcfgLHXcZE30eJrFUTQURpfv9EYCQ5C16Y8oq49wrer2QqM8Q6fMMock0ywuQbtEbVcTyr4DDNO1uSZ6LM3mK6u62St18uVmWbI5NMkmiHTxQiEGAIaTTiPfVB9RdVgdN0nRcEqov96Lbiwul5SFcCQiAZfN5+MSllNMOEKBngfsAAAXZJlovs6O553RnDzWx093SwzhN99803VXj8Vi1dTUdCpcvHixVCr98ssvOxauXLlSJBJ99NFHnrdyuXzPnj2jR4/u+kEGg2HVqlWpqTcPvsTFxYWE+JyqAxEgFEU1NzdHR0ffbkXud9CFuENwuVxarValulPC0N+3OJ1OPp8/aVIfuTJuydLoihUrVqxY4U3NwYMHnzp1qlNhVFTUxYsXPa/NZrPBYIiKiurSFAAApFLp2rVrA1EVgUAgEPc5tyGorkaj8bywWCzbtm3Lzr6RhGXr1q0tLS0AgEWLFh0+fLi5uRkAsHHjxmHDhsXE3P7AtQgEAoG4J7kN5wgHDRpEEERoaOjFixeHDx/+ww8/8Pl8AIBQKNy5c6fnCOqqVau2bNkycODAkpKS7du393kcEoFAIBAI/7gNhtDpdF66dMlkMsXFxcXFxbWXNzY2yuXy9mMSlZWVjY2NmZmZXY/bIxAIBAIRLO7uEGsIBAKBQATIXRl02+FwnDx5sv1tUlJSx5llOxUVFQUFBdHR0ZMnT/acSkQEnfr6+tOnT9M0PXLkyG6vQmlpaWtrq+c1l8sdO3Zsv+p3T3Px4sWzZ88mJyf39KtqtdpDhw7x+fwZM2bwePdCloA7EJ1OV1hYaDAYhg0b1u1x58rKyo4O85MmTSKIez7kX38DITx69Gj72+jo6I6nCdqpr68/duxYWFjYtGnTWKyb5u+unBHW19fHx8e3e8SuWLFi8eLFners3Lnz2WefXbhw4enTpwcMGLB58+Z+V/PeZ9u2bc8///yECRNIkty3b9+nn366bNmyTnVmz55dW1vrCZsQHh6+cePG26HpPci///3vv/zlL/Pnzz927NisWbM++eSTThWuXr06fvz46dOnazSalpaWgoICkSgYkVsRHSgrKxs9evS4ceMUCkVOTs7KlSvfe++9TnX++Mc/fv/990lJN5Jk7dmzBw1Kgo7b7SZJsn2QMX/+/N/85jed6pw4cWL+/PkLFiy4dOmSQCA4dOjQzREJvAupq6sTCAS9VGAYJi0tbfPmzRBCo9Eol8vPnDnTX9rdRzQ1NVmtVs/rDRs2KJXKrnVmzZq1fv36/tXr3sfpdIaFheXm5kIIm5qaeDxedXV1pzpLly595ZVXIIQMw4wfP/7TTz/tdzXvffR6vVar9bwuLS3FMKy1tbVTndWrV69evbrfVbu/cLlcAACTydRLnQkTJnzyyScQQofDkZycvHfv3vZ/3YbjE0GBYZjc3Nz8/HyLpZt83JWVldevX/fE9RaLxdOmTcvJyel3He99lEqlx+PX89rtdndb7fr16wcOHOgaTgHhN0VFRQzDTJgwAQCgVCpHjRr144+d48jk5OQsWrQIAIBh2MKFC9EjcCuQSqVyudzz2jMQ7PYpaGlp2b9//6VLl/pXu/uOgoKC3Nxcg6GbkEAmkykvL8/zRHA4nDlz5nR8Iu5WQ6hQKD7++ONXXnklISEhNze3038bGxtDQ0O53BshWVUqVWNjY7/reB/BMMy77777q1/9quu/uFzuiRMn/vWvfw0ZMuTFF1/sf93uSRobG1UqVfvOt0qlampq6ljB4XC0tbW1R6JAj0A/sGbNmtmzZ0dERHQqx3G8vLz8yy+/nDx58syZMx0O3+I+IrwkIiLis88++/Of/xwXF7djx45O/21qasJxvD20dacn4g51ljGbzd2eHXz//fdnzpypUqlqamo8vcCHH364YsWK6urqjtVomu7oHUMQBEVRt1rne5WRI0c6nc5OhatWrVqyZInnNYTwpZdeoijqb3/7W9fmW7du9SzE19bWDh06dO7cuQ8++OCt1vmep887nKZpAEB7HfQI3Gq++OKL/fv3d3Tia+ftt9/2PAIWi2XUqFGff/75qlWr+l3Bexw2m93Q0OD5nTdu3LhixYrZs2d3zFnkeWR6eiLuUEMoEAi69arwBFHsmMLwiSeeePXVV/V6vUwmay9UKpVtbW0URXn8gtRqddccFwgvWbduHdMlnG7H3/MPf/jD2bNnDx8+3K0LQPt2dGxs7JgxY0pKSpAhDBylUtkeoQkAoFarMzMzO1YQCAQikUir1XqiMqnV6sjIyP7W8r5h7dq1//M//3P8+PFu+5n2R0AoFM6ZM6ekpKR/tbtfaP+dH3vssWXLllVVVaWnp7f/NyIigqZpnU6nUChAV6Nwi7cwbzl79uwRi8UMw0AILRaL2WyGELrdbpVKdeTIEc/rmJiYQ4cO3WZF71H+9Kc/ZWZm6nS6joWe9COdajocjvj4+O+++64ftbtnMRqNQqHw4sWLEEKLxSIWi8+fPw8hdDqder3eU2fu3Lnvvvuu5/WCBQvWrFlzu7S9t/n222+VSuWVK1c6Fjqdzra2tq6Vp0+f/vrrr/eXavcpRUVFOI4bjUb4y75o8ODBGzduhBAyDJOVldXRie+uPD7x2WefnTt3Li0tTa1Wr127ds2aNb/97W8BAL/+9a/NZvOGDRsAAJ9++umHH374u9/9Ljc3V6vVFhYWoqOEQWfz5s1PPPHEokWLQkNDPSWffPIJj8d7++238/Lyjhw50tbWtmDBgkmTJnE4nB07dkAICwoK/MixjOjKG2+8sWvXrmeffXb37t1isXj37t0AgPXr17/zzjvXrl0DABQUFMyaNevVV1/VaDRbt24tLS3tun2FCJDz589nZWWNHz++PZfca6+9lpiYuHPnzhdeeMETPPnBBx/Mzs6WSCTHjx8vLS0tLi5GC1RBZ/Pmzfv27Rs0aJDBYFi7du3KlSvfeecdAMCaNWvy8/MPHz4MANi6deuLL7742muvlZSUFBcXl5aWtvuR3JWGsK6uLicnp76+XiaTTZkyJSsry1NeUFDgdrsnTpzoeXvgwIETJ06oVKrly5cLBILbpu69S1lZWWFhYceS5cuXkyRZUlLS3Nw8a9YsiqJ27dpVVlbGMEx6evrDDz/MZvuSYxvRMxDCnTt3njlzJjExcenSpSRJAgAqKipKSkoeffRRT53z58/v2LGDx+MtWbIEpQS6FTQ1NXVyx33ooYciIiJqa2tPnjz55JNPAgAOHz5cVFRks9ni4uIef/xxdJrzVqBWq/fs2VNTUyMQCMaPH98eYqKkpKSlpWXmzJmetydPnjxw4EBISMjTTz/dcTftrjSECAQCgUAEi7v1+AQCgUAgEEEBGUIEAoFA3NcgQ4hAIBCI+xpkCBEIBAJxX4MMIQKBQCDua5AhRCAQCMR9zR0aYg2BQHjJkSNHPOGDExISuo3Q25W9e/e2tbUBAAYMGDB8+PBbqx8CcceDDCECcXfzwQcfnD59euDAgdOmTWs3hN98882ZM2eKi4t1Ot2rr776/PPPd2yyffv2ysrKoqKi3/zmN8gQIhDIECIQdz1ZWVlHjx7tWPLCCy+oVKrU1NQzZ87o9fpO9b/99lsAQFhYWL9piEDcySBDiEDcg7S0tMhkstra2ri4uNutCwJxp4OcZRCIOxq9Xh8SErJ+/fpeSrrSMY4iAoHoHWQIEYg7GgihXq/vmBu5awkCgQgEZAgRCAQCcV+DDCECgUAg7muQIUQgEAjEfQ0yhAjEHQ2LxQIAUBTVXmIymW6fOgjEPQgyhAjEHY1YLBaLxdevX28vycvLu436IBD3HugcIQJxpzN9+vR169bNmDFjyJAh+fn5a9as6bNJXl6eRqPRarUAgLKysh9++AEAMHfuXC6Xe8vVRSDuNpAhRCDudD744IN58+ZNmzYNABAVFfXVV1/Nnj279yZvvfVWbm6u5/WmTZs2bdoEAGhqalIqlbdaWwTirgMZQgTiTicuLq6kpKSqqspisQwcOJDFYkEIe29y7Nix/tENgbgHQHuECMRdAI7jSUlJmZmZHt+ZTuTm5pIkuXTpUi+lZWdnkyTpWThFIBBYn0NLBAJxJ1NfX2+xWAAAEokkMjLSmybV1dUOhwMAEBoaikJvIxDIECIQCATivgYtjSIQCATivgYZQgQCgUDc1yBDiEAgEIj7GmQIEQgEAnFf8/8cWhKiMT6HrwAAAABJRU5ErkJggg==", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 3 + } + ], + "cell_type": "code", + "source": [ + "phase_plot(f + g * u, 200, 10.0, [[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x1 != 0 || x2 != 0])" + ], + "metadata": {}, + "execution_count": 3 + }, + { + "cell_type": "markdown", + "source": [ + "## Example 2" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "-3.470949347992857x₂³ - 6.465434558023581x₁x₂² + 4.004075892877742x₁²x₂ - 3.1387619181637865x₁³", + "text/latex": "$$ -3.470949347992857x_{2}^{3} - 6.465434558023581x_{1}x_{2}^{2} + 4.004075892877742x_{1}^{2}x_{2} - 3.1387619181637865x_{1}^{3} $$" + }, + "metadata": {}, + "execution_count": 4 + } + ], + "cell_type": "code", + "source": [ + "g = [0, 1]\n", + "f = [2x[1]^3 + x[1]^2*x[2] - 6x[1]*x[2]^2 + 5x[2]^3, 0]\n", + "b = x[1]^2 + x[2]^2\n", + "u = controller(f, g, b, 2.5, 0:3)" + ], + "metadata": {}, + "execution_count": 4 + }, + { + "cell_type": "markdown", + "source": [ + "We find the controller above which gives the following phase plot." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: To maintain consistency with solution indexing, keyword argument vars will be removed in a future version. Please use keyword argument idxs instead.\n", + "│ caller = ip:0x0\n", + "└ @ Core :-1\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=23}", + "image/png": "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", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 5 + } + ], + "cell_type": "code", + "source": [ + "phase_plot(f + g * u, 2000, 5.0, [[-1.0, -5.0], [1.0, 5.0]])" + ], + "metadata": {}, + "execution_count": 5 + }, + { + "cell_type": "markdown", + "source": [ + "## Example 3" + ], + "metadata": {} + }, + { + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": "-2.737433441558844x₂² + 0.18059594494782605x₁²", + "text/latex": "$$ -2.737433441558844x_{2}^{2} + 0.18059594494782605x_{1}^{2} $$" + }, + "metadata": {}, + "execution_count": 6 + } + ], + "cell_type": "code", + "source": [ + "g = [0, x[2]]\n", + "f = [-6x[1]*x[2]^2 - x[1]^2*x[2] + 2x[2]^3, 0]\n", + "b = x[1]^2 + x[2]^2\n", + "u = controller(f, g, b, 3, 0:2)" + ], + "metadata": {}, + "execution_count": 6 + }, + { + "cell_type": "markdown", + "source": [ + "We find the controller above which gives the following phase plot." + ], + "metadata": {} + }, + { + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "┌ Warning: To maintain consistency with solution indexing, keyword argument vars will be removed in a future version. Please use keyword argument idxs instead.\n", + "│ caller = ip:0x0\n", + "└ @ Core :-1\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": "Plot{Plots.GRBackend() n=31}", + "image/png": "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", + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "metadata": {}, + "execution_count": 7 + } + ], + "cell_type": "code", + "source": [ + "X0 = [Float64[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x2 != 0]\n", + "ε = 1e-4 # We separate the starting point slightly from the hyperplane `x2 = 0` which is invariant.\n", + "push!(X0, [-4, ε])\n", + "push!(X0, [-3, -ε])\n", + "push!(X0, [ 3, ε])\n", + "push!(X0, [ 4, -ε])\n", + "phase_plot(f + g * u, 2000, 10.0, X0)" + ], + "metadata": {}, + "execution_count": 7 + }, + { + "cell_type": "markdown", + "source": [ + "---\n", + "\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ], + "metadata": {} + } + ], + "nbformat_minor": 3, + "metadata": { + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.3" + }, + "kernelspec": { + "name": "julia-1.10", + "display_name": "Julia 1.10.3", + "language": "julia" + } + }, + "nbformat": 4 +} diff --git a/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems.jl b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems.jl new file mode 100644 index 000000000..e42ac2e28 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems.jl @@ -0,0 +1,74 @@ +using DynamicPolynomials +@polyvar x[1:2] + +using SumOfSquares +using CSDP +using LinearAlgebra # for ⋅ +using MultivariatePolynomials +divergence(f) = sum(differentiate.(f, x)) +function controller(f, g, b, α, degs) + solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + model = SOSModel(solver) + a = 1 + monos = monomials(x, degs) + N = length(monos) + 1 + @variable(model, c[1:N] in MOI.NormOneCone(N)) + c_poly = polynomial(c[2:end], monos) + fagc = f * a + g * c_poly + @constraint(model, b * divergence(fagc) - α * differentiate(b, x) ⋅ fagc in SOSCone()) + @objective(model, Min, c[1]) + optimize!(model) + if termination_status(model) != MOI.OPTIMAL + @warn("Termination status $(termination_status(model)): $(raw_status(model))") + end + u = value(c_poly) / value(a) + return MultivariatePolynomials.map_coefficients(coef -> abs(coef) < 1e-6 ? 0.0 : coef, u) +end + +import DifferentialEquations, Plots +function phase_plot(f, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5()) + ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f] + ∇pt(v, p, t) = ∇(v[1], v[2]) + function traj(v0) + tspan = (0.0, Δt) + prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan) + return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8) + end + ticks = -5:0.5:5 + X = repeat(ticks, 1, length(ticks)) + Y = X' + Plots.quiver(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5) + for x0 in X0 + Plots.plot!(traj(x0), vars=(1, 2), label = nothing) + end + Plots.plot!(xlims = (-5, 5), ylims = (-5, 5)) +end + +g = [0, 1] +f = [x[2] - x[1]^3 + x[1]^2, 0] +b = 3x[1]^2 + 2x[1]*x[2] + 2x[2]^2 +u = controller(f, g, b, 4, 0:3) + +phase_plot(f + g * u, 200, 10.0, [[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x1 != 0 || x2 != 0]) + +g = [0, 1] +f = [2x[1]^3 + x[1]^2*x[2] - 6x[1]*x[2]^2 + 5x[2]^3, 0] +b = x[1]^2 + x[2]^2 +u = controller(f, g, b, 2.5, 0:3) + +phase_plot(f + g * u, 2000, 5.0, [[-1.0, -5.0], [1.0, 5.0]]) + +g = [0, x[2]] +f = [-6x[1]*x[2]^2 - x[1]^2*x[2] + 2x[2]^3, 0] +b = x[1]^2 + x[2]^2 +u = controller(f, g, b, 3, 0:2) + +X0 = [Float64[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x2 != 0] +ε = 1e-4 # We separate the starting point slightly from the hyperplane `x2 = 0` which is invariant. +push!(X0, [-4, ε]) +push!(X0, [-3, -ε]) +push!(X0, [ 3, ε]) +push!(X0, [ 4, -ε]) +phase_plot(f + g * u, 2000, 10.0, X0) + +# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl diff --git a/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/357a8ff1.svg b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/357a8ff1.svg new file mode 100644 index 000000000..0c7a9f137 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/357a8ff1.svg @@ -0,0 +1,1367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/92fa3419.svg b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/92fa3419.svg new file mode 100644 index 000000000..ab4e033b3 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/92fa3419.svg @@ -0,0 +1,1373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/e5219415.svg b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/e5219415.svg new file mode 100644 index 000000000..6bda5df3b --- /dev/null +++ b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/e5219415.svg @@ -0,0 +1,1375 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/index.html b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/index.html new file mode 100644 index 000000000..ad0d6f522 --- /dev/null +++ b/previews/PR347/generated/Systems and Control/stabilization_of_nonlinear_systems/index.html @@ -0,0 +1,61 @@ + +Stabilization of nonlinear systems · SumOfSquares

Stabilization of nonlinear systems

Adapted from: Examples 1, 2 and 3 of [PPA04]

[PPA04] Prajna, Stephen, Pablo A. Parrilo, and Anders Rantzer. Nonlinear control synthesis by convex optimization. IEEE Transactions on Automatic Control 49.2 (2004): 310-314.

using DynamicPolynomials
+@polyvar x[1:2]
+
+using SumOfSquares
+using CSDP
+using LinearAlgebra # for ⋅
+using MultivariatePolynomials
+divergence(f) = sum(differentiate.(f, x))
+function controller(f, g, b, α, degs)
+    solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
+    model = SOSModel(solver)
+    a = 1
+    monos = monomials(x, degs)
+    N = length(monos) + 1
+    @variable(model, c[1:N] in MOI.NormOneCone(N))
+    c_poly = polynomial(c[2:end], monos)
+    fagc = f * a + g * c_poly
+    @constraint(model, b * divergence(fagc) - α * differentiate(b, x) ⋅ fagc in SOSCone())
+    @objective(model, Min, c[1])
+    optimize!(model)
+    if termination_status(model) != MOI.OPTIMAL
+        @warn("Termination status $(termination_status(model)): $(raw_status(model))")
+    end
+    u = value(c_poly) / value(a)
+    return MultivariatePolynomials.map_coefficients(coef -> abs(coef) < 1e-6 ? 0.0 : coef, u)
+end
+
+import DifferentialEquations, Plots
+function phase_plot(f, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5())
+    ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f]
+    ∇pt(v, p, t) = ∇(v[1], v[2])
+    function traj(v0)
+        tspan = (0.0, Δt)
+        prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan)
+        return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8)
+    end
+    ticks = -5:0.5:5
+    X = repeat(ticks, 1, length(ticks))
+    Y = X'
+    Plots.quiver(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5)
+    for x0 in X0
+        Plots.plot!(traj(x0), vars=(1, 2), label = nothing)
+    end
+    Plots.plot!(xlims = (-5, 5), ylims = (-5, 5))
+end
phase_plot (generic function with 2 methods)

Example 1

g = [0, 1]
+f = [x[2] - x[1]^3 + x[1]^2, 0]
+b = 3x[1]^2 + 2x[1]*x[2] + 2x[2]^2
+u = controller(f, g, b, 4, 0:3)

\[ -0.5738994625385273x_{2} - 1.2298305281744644x_{1} - 0.12930340072544455x_{2}^{3} \]

We find the controller above which gives the following phase plot.

phase_plot(f + g * u, 200, 10.0, [[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x1 != 0 || x2 != 0])
Example block output

Example 2

g = [0, 1]
+f = [2x[1]^3 + x[1]^2*x[2] - 6x[1]*x[2]^2 + 5x[2]^3, 0]
+b = x[1]^2 + x[2]^2
+u = controller(f, g, b, 2.5, 0:3)

\[ -3.470949347992857x_{2}^{3} - 6.465434558023581x_{1}x_{2}^{2} + 4.004075892877742x_{1}^{2}x_{2} - 3.1387619181637865x_{1}^{3} \]

We find the controller above which gives the following phase plot.

phase_plot(f + g * u, 2000, 5.0, [[-1.0, -5.0], [1.0, 5.0]])
Example block output

Example 3

g = [0, x[2]]
+f = [-6x[1]*x[2]^2 - x[1]^2*x[2] + 2x[2]^3, 0]
+b = x[1]^2 + x[2]^2
+u = controller(f, g, b, 3, 0:2)

\[ -2.737433441558844x_{2}^{2} + 0.18059594494782605x_{1}^{2} \]

We find the controller above which gives the following phase plot.

X0 = [Float64[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x2 != 0]
+ε = 1e-4 # We separate the starting point slightly from the hyperplane `x2 = 0` which is invariant.
+push!(X0, [-4,  ε])
+push!(X0, [-3, -ε])
+push!(X0, [ 3,  ε])
+push!(X0, [ 4, -ε])
+phase_plot(f + g * u, 2000, 10.0, X0)
Example block output

This page was generated using Literate.jl.

diff --git a/previews/PR347/index.html b/previews/PR347/index.html new file mode 100644 index 000000000..6d755ab14 --- /dev/null +++ b/previews/PR347/index.html @@ -0,0 +1,2 @@ + +Index · SumOfSquares
diff --git a/previews/PR347/objects.inv b/previews/PR347/objects.inv new file mode 100644 index 000000000..a4eac509c Binary files /dev/null and b/previews/PR347/objects.inv differ diff --git a/previews/PR347/references.bib b/previews/PR347/references.bib new file mode 100644 index 000000000..63e63e9f0 --- /dev/null +++ b/previews/PR347/references.bib @@ -0,0 +1,51 @@ + +@Book{Floudas1999, + author = {Floudas, Christodoulos A. and Pardalos, Pãnos M. and Adjiman, Claire S. and Esposito, William R. and Gümüş, Zeynep H. and Harding, Stephen T. and Klepeis, John L. and Meyer, Clifford A. and Schweiger, Carl A.}, + publisher = {Springer US}, + title = {Handbook of Test Problems in Local and Global Optimization}, + year = {1999}, + isbn = {9781475730401}, + doi = {10.1007/978-1-4757-3040-1}, + issn = {1571-568X}, + journal = {Nonconvex Optimization and Its Applications}, +} + +@Article{Hesse1973, + author = {Hesse, Rick}, + journal = {Operations Research}, + title = {A Heuristic Search Procedure for Estimating a Global Solution of Nonconvex Programming Problems}, + year = {1973}, + issn = {1526-5463}, + month = dec, + number = {6}, + pages = {1267--1280}, + volume = {21}, + doi = {10.1287/opre.21.6.1267}, + publisher = {Institute for Operations Research and the Management Sciences (INFORMS)}, +} + +@Book{Lasserre2009, + author = {Lasserre, Jean Bernard}, + publisher = {Imperial College Press}, + title = {Moments, Positive Polynomials and Their Applications}, + year = {2009}, + isbn = {9781848164468}, + month = oct, + doi = {10.1142/p665}, + file = {:ebooks/Lasserre_2009_Moments, positive polynomials and their applications.pdf:PDF}, + issn = {2399-1593}, + journal = {Series on Optimization and Its Applications}, +} + +@InBook{Laurent2008, + author = {Laurent, Monique}, + pages = {157--270}, + publisher = {Springer New York}, + title = {Sums of Squares, Moment Matrices and Optimization Over Polynomials}, + year = {2008}, + isbn = {9780387096865}, + month = sep, + booktitle = {The IMA Volumes in Mathematics and its Applications}, + doi = {10.1007/978-0-387-09686-5_7}, + issn = {0940-6573}, +} diff --git a/previews/PR347/search_index.js b/previews/PR347/search_index.js new file mode 100644 index 000000000..17498b2c9 --- /dev/null +++ b/previews/PR347/search_index.js @@ -0,0 +1,3 @@ +var documenterSearchIndex = {"docs": +[{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"EditURL = \"../../tutorials/Getting started/sos_decomposition.jl\"","category":"page"},{"location":"generated/Getting started/sos_decomposition/#A-trivial-SOS-decomposition-example","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"","category":"section"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"(Image: ) (Image: ) Contributed by: votroto Adapted from: Examples 3.25 of [BPT12]","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"using DynamicPolynomials\nusing SumOfSquares\nimport CSDP","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"The polynomial p = x^2 - x*y^2 + y^4 + 1 is SOS. We can, for example, decompose it as p = 3/4*(x - y^2)^2 + 1/4*(x + y)^2 + 1, which clearly proves that p is SOS, and there are infinitely many other ways to decompose p into sums of squares.","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"We can use SumOfSquares.jl to find such decompositions.","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"First, setup the polynomial of interest.","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"@polyvar x y\np = x^2 - x*y^2 + y^4 + 1","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"Secondly, constrain the polynomial to be nonnegative. SumOfSquares.jl transparently reinterprets polyonmial nonnegativity as the appropriate SOS certificate for polynomials nonnegative on semialgebraic sets.","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"model = SOSModel(CSDP.Optimizer)\n@constraint(model, cref, p >= 0)","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"Thirdly, optimize the feasibility problem!","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"optimize!(model)","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"Lastly, recover a SOS decomposition. In general, SOS decompositions are not unique!","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"sos_dec = sos_decomposition(cref, 1e-4)","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"Converting, rounding, and simplifying - Huzza, Back where we began!","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"polynomial(sos_dec, Float32)","category":"page"},{"location":"generated/Getting started/sos_decomposition/#A-deeper-explanation-and-the-unexplained-1e-4-parameter","page":"A trivial SOS decomposition example","title":"A deeper explanation and the unexplained 1e-4 parameter","text":"","category":"section"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"p = x^2 - x*y^2 + y^4 + 1 can be represented in terms of its Gram matrix as","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"gram = gram_matrix(cref)","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"gram.basis.monomials' * gram.Q * gram.basis.monomials","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"where the matrix gram.Q is positive semidefinite, because p is SOS. If we could only get the decomposition gram.Q = V' * V, the SOS decomposition would simply be ||V * monomials||^2.","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"Unfortunately, we can not use Cholesky decomposition, since gram Q is only semidefinite, not definite. Hence, SumOfSquares.jl uses SVD decomposition instead and discards small singular values (in our case 1e-4).","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"","category":"page"},{"location":"generated/Getting started/sos_decomposition/","page":"A trivial SOS decomposition example","title":"A trivial SOS decomposition example","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"EditURL = \"../../tutorials/Polynomial Optimization/bound_on_global_extremum.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/#Bound-on-Global-Extremum","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"","category":"section"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"(Image: ) (Image: ) Adapted from: SOSTOOLS' SOSDEMO3 (See Section 4.3 of SOSTOOLS User's Manual)","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"using DynamicPolynomials\n@polyvar x1 x2","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"The Goldstein-Price function f(x) is defined as follows:","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"f1 = x1 + x2 + 1\nf2 = 19 - 14x1 + 3x1^2 - 14x2 + 6x1*x2 + 3x2^2\nf3 = 2x1 - 3x2\nf4 = 18 - 32x1 + 12x1^2 + 48x2 - 36x1*x2 + 27x2^2\nf = (1 + f1^2 * f2) * (30 + f3^2 * f4)","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"using SumOfSquares\nusing CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = SOSModel(solver);\nnothing #hide","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"We create the decision variable gamma that will be the lower bound to the Goldstein-Price function. We maximize it to have the highest possible lower bound.","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"@variable(model, γ)\n@objective(model, Max, γ)","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"We constrain gamma to be a lower bound with the following constraint that ensures that f(x_1 x_2) ge gamma for all x_1 x_2.","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"@constraint(model, f >= γ)\n\nJuMP.optimize!(model)","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"We verify that the solver has found a feasible solution:","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"JuMP.primal_status(model)","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"We can now obtain the lower bound either with value(γ) or objective_value(model):","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"objective_value(model)","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"","category":"page"},{"location":"generated/Polynomial Optimization/bound_on_global_extremum/","page":"Bound on Global Extremum","title":"Bound on Global Extremum","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"EditURL = \"../../tutorials/Symmetry/permutation_symmetry.jl\"","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/#Symmetry-reduction","page":"Symmetry reduction","title":"Symmetry reduction","text":"","category":"section"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"(Image: ) (Image: ) Adapted from: SymbolicWedderburn example","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"import MutableArithmetics as MA\nusing MultivariatePolynomials\nusing MultivariateBases\n\nusing DynamicPolynomials\n@polyvar x[1:4]","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"We would like to find the minimum value of the polynomial","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"poly = sum(x) + sum(x.^2)","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"As we can decouple the problem for each x[i] for which x[i] + x[i]^2 has minimum value 0.25, we would expect to get -1 as answer. Can this decoupling be exploited by SumOfSquares as well ? For this, we need to use a certificate that can exploit the permutation symmetry of the polynomial.","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"using SumOfSquares","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"We define the symmetry group as a permutation group in the variables. In order to do that, we define the action of a permutation on a monomial as the monomial obtained after permuting the variables.","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"using PermutationGroups\nG = PermGroup([perm\"(1,2,3,4)\"])","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"We can use this certificate as follows:","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"import CSDP\nsolver = CSDP.Optimizer\nmodel = Model(solver)\n@variable(model, t)\n@objective(model, Max, t)\npattern = Symmetry.Pattern(G, Symmetry.VariablePermutation())\ncon_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\noptimize!(model)\nvalue(t)","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"We indeed find -1, let's verify that symmetry was exploited:","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"gram_matrix(con_ref).blocks","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"","category":"page"},{"location":"generated/Symmetry/permutation_symmetry/","page":"Symmetry reduction","title":"Symmetry reduction","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"EditURL = \"../../tutorials/Systems and Control/stabilization_of_nonlinear_systems.jl\"","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/#Stabilization-of-nonlinear-systems","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"","category":"section"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"(Image: ) (Image: ) Adapted from: Examples 1, 2 and 3 of [PPA04]","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"[PPA04] Prajna, Stephen, Pablo A. Parrilo, and Anders Rantzer. Nonlinear control synthesis by convex optimization. IEEE Transactions on Automatic Control 49.2 (2004): 310-314.","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"using DynamicPolynomials\n@polyvar x[1:2]\n\nusing SumOfSquares\nusing CSDP\nusing LinearAlgebra # for ⋅\nusing MultivariatePolynomials\ndivergence(f) = sum(differentiate.(f, x))\nfunction controller(f, g, b, α, degs)\n solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n model = SOSModel(solver)\n a = 1\n monos = monomials(x, degs)\n N = length(monos) + 1\n @variable(model, c[1:N] in MOI.NormOneCone(N))\n c_poly = polynomial(c[2:end], monos)\n fagc = f * a + g * c_poly\n @constraint(model, b * divergence(fagc) - α * differentiate(b, x) ⋅ fagc in SOSCone())\n @objective(model, Min, c[1])\n optimize!(model)\n if termination_status(model) != MOI.OPTIMAL\n @warn(\"Termination status $(termination_status(model)): $(raw_status(model))\")\n end\n u = value(c_poly) / value(a)\n return MultivariatePolynomials.map_coefficients(coef -> abs(coef) < 1e-6 ? 0.0 : coef, u)\nend\n\nimport DifferentialEquations, Plots\nfunction phase_plot(f, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5())\n ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f]\n ∇pt(v, p, t) = ∇(v[1], v[2])\n function traj(v0)\n tspan = (0.0, Δt)\n prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan)\n return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8)\n end\n ticks = -5:0.5:5\n X = repeat(ticks, 1, length(ticks))\n Y = X'\n Plots.quiver(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5)\n for x0 in X0\n Plots.plot!(traj(x0), vars=(1, 2), label = nothing)\n end\n Plots.plot!(xlims = (-5, 5), ylims = (-5, 5))\nend","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/#Example-1","page":"Stabilization of nonlinear systems","title":"Example 1","text":"","category":"section"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"g = [0, 1]\nf = [x[2] - x[1]^3 + x[1]^2, 0]\nb = 3x[1]^2 + 2x[1]*x[2] + 2x[2]^2\nu = controller(f, g, b, 4, 0:3)","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"We find the controller above which gives the following phase plot.","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"phase_plot(f + g * u, 200, 10.0, [[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x1 != 0 || x2 != 0])","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/#Example-2","page":"Stabilization of nonlinear systems","title":"Example 2","text":"","category":"section"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"g = [0, 1]\nf = [2x[1]^3 + x[1]^2*x[2] - 6x[1]*x[2]^2 + 5x[2]^3, 0]\nb = x[1]^2 + x[2]^2\nu = controller(f, g, b, 2.5, 0:3)","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"We find the controller above which gives the following phase plot.","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"phase_plot(f + g * u, 2000, 5.0, [[-1.0, -5.0], [1.0, 5.0]])","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/#Example-3","page":"Stabilization of nonlinear systems","title":"Example 3","text":"","category":"section"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"g = [0, x[2]]\nf = [-6x[1]*x[2]^2 - x[1]^2*x[2] + 2x[2]^3, 0]\nb = x[1]^2 + x[2]^2\nu = controller(f, g, b, 3, 0:2)","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"We find the controller above which gives the following phase plot.","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"X0 = [Float64[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x2 != 0]\nε = 1e-4 # We separate the starting point slightly from the hyperplane `x2 = 0` which is invariant.\npush!(X0, [-4, ε])\npush!(X0, [-3, -ε])\npush!(X0, [ 3, ε])\npush!(X0, [ 4, -ε])\nphase_plot(f + g * u, 2000, 10.0, X0)","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"","category":"page"},{"location":"generated/Systems and Control/stabilization_of_nonlinear_systems/","page":"Stabilization of nonlinear systems","title":"Stabilization of nonlinear systems","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"EditURL = \"../../tutorials/Symmetry/cyclic.jl\"","category":"page"},{"location":"generated/Symmetry/cyclic/#Cyclic-symmetry-for-Sums-of-Hermitian-Squares","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"","category":"section"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"(Image: ) (Image: )","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"We start by defining the Cyclic group.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"using GroupsCore\nimport PermutationGroups\n\nstruct CyclicElem <: GroupElement\n n::Int\n id::Int\nend\nBase.:(==)(a::CyclicElem, b::CyclicElem) = a.n == b.n && a.id == b.id\nBase.inv(el::CyclicElem) = CyclicElem(el.n, (el.n - el.id) % el.n)\n\nfunction Base.:*(a::CyclicElem, b::CyclicElem)\n return CyclicElem(a.n, (a.id + b.id) % a.n)\nend\nBase.:^(el::CyclicElem, k::Integer) = CyclicElem(el.n, (el.id * k) % el.n)\n\nBase.conj(a::CyclicElem, b::CyclicElem) = inv(b) * a * b\nBase.:^(a::CyclicElem, b::CyclicElem) = conj(a, b)\n\nfunction PermutationGroups.order(el::CyclicElem)\n return div(el.n, gcd(el.n, el.id))\nend\n\nstruct CyclicGroup <: Group\n n::Int\nend\nBase.eltype(::CyclicGroup) = CyclicElem\nBase.one(c::Union{CyclicGroup, CyclicElem}) = CyclicElem(c.n, 0)\nPermutationGroups.gens(c::CyclicGroup) = [CyclicElem(c.n, 1)]\nPermutationGroups.order(::Type{T}, c::CyclicGroup) where {T} = convert(T, c.n)\nfunction Base.iterate(c::CyclicGroup, prev::CyclicElem=CyclicElem(c.n, -1))\n id = prev.id + 1\n if id >= c.n\n return nothing\n else\n next = CyclicElem(c.n, id)\n return next, next\n end\nend","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"Now we define that the cyclic group acts on monomial by permuting variables cyclically. So for instance, CyclicElem(3, 1) would transform x_1^3*x_2*x_3^4 into x_1^4*x_2^3*x_3.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"import MultivariatePolynomials as MP\n\nusing SumOfSquares\n\nstruct Action{V<:MP.AbstractVariable} <: Symmetry.OnMonomials\n variables::Vector{V}\nend\nSymmetry.SymbolicWedderburn.coeff_type(::Action) = Float64\nfunction Symmetry.SymbolicWedderburn.action(a::Action, el::CyclicElem, mono::MP.AbstractMonomial)\n return prod(MP.powers(mono), init=MP.constant_monomial(mono)) do (var, exp)\n index = findfirst(isequal(var), a.variables)\n new_index = mod1(index + el.id, el.n)\n return a.variables[new_index]^exp\n end\nend\n\nusing DynamicPolynomials\n@polyvar x[1:3]\naction = Action(x)\ng = CyclicElem(3, 1)\nSymmetry.SymbolicWedderburn.action(action, g, x[1]^3 * x[2] * x[3]^4)","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"The following polynomial poly is invariant under the action of the group G.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"N = 3\nG = CyclicGroup(N)\npoly = sum(x[i] * x[mod1(i + 1, N)] for i in 1:N) + sum(x.^2)\nSymmetry.SymbolicWedderburn.action(action, g, poly)","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"Let's now find the minimum of p by exploiting this symmetry.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"import CSDP\nsolver = CSDP.Optimizer\nmodel = Model(solver)\n@variable(model, t)\n@objective(model, Max, t)\npattern = Symmetry.Pattern(G, action)\ncon_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\noptimize!(model)\nsolution_summary(model)","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"Let's look at the symmetry adapted basis used.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"for gram in gram_matrix(con_ref).blocks\n println(gram.basis.polynomials)\n display(gram.Q)\nend","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"Let's look into more details at the last two elements of the basis.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"basis = [(x[1] + x[2] - 2x[3])/√6, (x[1] - x[2])/√2]","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"This actually constitutes the basis for an invariant subspace corresponding to a group character of degree 2 and multiplicity 1. This means that it decomposes the semidefinite matrix into 2 blocks of size 1-by-1 that are equal. Indeed, we see above that gram.Q is identically equal for both. As the group is generated by one element g, we can just verify it by verifying its invariance under g. The image of each element under the basis is:","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"image = [Symmetry.SymbolicWedderburn.action(action, g, p) for p in basis]","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"We can see that they are both still in the same 2-dimensional subspace.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"a = -1/2\nb = √3/2\n[a -b; b a] * basis","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"In fact, these last two basis comes from the real decomposition of a complex one.","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"import CSDP\nsolver = CSDP.Optimizer\nmodel = Model(solver)\n@variable(model, t)\n@objective(model, Max, t)\npattern = Symmetry.Pattern(G, action)\ncone = SumOfSquares.NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}()\ncon_ref = @constraint(model, poly - t in cone, symmetry = pattern)\noptimize!(model)\nsolution_summary(model)\n\nfor gram in gram_matrix(con_ref).blocks\n println(gram.basis.polynomials)\n display(gram.Q)\nend","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"We can see that the real invariant subspace was in fact coming from two complex conjugate complex invariant subspaces:","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"complex_basis = basis[1] + im * basis[2]\nimage = Symmetry.SymbolicWedderburn.action(action, g, complex_basis)","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"And there is a direct correspondance between the representation of the real and complex versions:","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"(a + b * im) * complex_basis","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"","category":"page"},{"location":"generated/Symmetry/cyclic/","page":"Cyclic symmetry for Sums of Hermitian Squares","title":"Cyclic symmetry for Sums of Hermitian Squares","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"EditURL = \"../../tutorials/Symmetry/even_reduction.jl\"","category":"page"},{"location":"generated/Symmetry/even_reduction/#Even-reduction","page":"Even reduction","title":"Even reduction","text":"","category":"section"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"(Image: ) (Image: )","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"using DynamicPolynomials\n@polyvar x","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"We would like to find the minimum value of the following polynomial:","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"poly = x^4 - 2x^2\n\nusing SumOfSquares","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"We define the custom action as follows:","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"struct OnSign <: Symmetry.OnMonomials end\nusing PermutationGroups\nimport SymbolicWedderburn\nSymbolicWedderburn.coeff_type(::OnSign) = Float64\nfunction SymbolicWedderburn.action(::OnSign, p::Permutation, mono::AbstractMonomial)\n if isone(p) || iseven(DynamicPolynomials.degree(mono))\n return 1 * mono\n else\n @assert p.perm == perm\"(1,2)\"\n return -1 * mono\n end\nend\nG = PermGroup([perm\"(1,2)\"])","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"We can exploit the symmetry as follows:","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"import CSDP\nsolver = CSDP.Optimizer\nmodel = Model(solver)\n@variable(model, t)\n@objective(model, Max, t)\npattern = Symmetry.Pattern(G, OnSign())\ncon_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\noptimize!(model)\nvalue(t)","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"We indeed find -1, let's verify that symmetry was exploited:","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"gram_matrix(con_ref)","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"","category":"page"},{"location":"generated/Symmetry/even_reduction/","page":"Even reduction","title":"Even reduction","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"EditURL = \"../../tutorials/Systems and Control/julia_set.jl\"","category":"page"},{"location":"generated/Systems and Control/julia_set/#Outer-approximation-of-Julia-set","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"","category":"section"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"(Image: ) (Image: ) Adapted from: Section 7.1.3 of [KHJ14]","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"[KHJ14] Milan Korda, Didier Henrion, and Colin N. Jones. Convex computation of the maximum controlled invariant set for polynomial control systems. SIAM Journal on Control and Optimization 52.5 (2014): 2944-2969.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"The Julia map is defined as follows:","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"function julia_map(point, c)\n a, b = point\n return [a^2 - b^2 + real(c), 2a * b + imag(c)]\nend","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"The *escape radius\" is the radius r such that r^2 ≥ r + abs(c). Ouside of the circle of that radius, all points diverge so we know the Julia set belongs to that circle.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"escape_radius(c) = (1 + √(1 + 4 * abs(c))) / 2","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"To check whether a point is in the Julia set, we can iterate and once the point leaves the circle of escape radius, we consider that it is not in the Julia set, if it stays in the set, we consider that it is in the Julia set. This gives an outer approximation that converges to the Julia set when m increases.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"using LinearAlgebra\nfunction in_set(x, c, m=2000)\n r = escape_radius(c)\n for i in 1:m\n if norm(x) > r\n return false\n end\n x = julia_map(x, c)\n end\n return true\nend","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"To sort of minimize a level set of a polynomial we minimize integral of that polynomial. We borrow the following from https://doi.org/10.1080/00029890.2001.11919774","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"using SpecialFunctions\nusing DynamicPolynomials\nβ(α) = (α + 1) / 2\nfunction circle_integral(mono::AbstractMonomial)\n if any(isodd, exponents(mono))\n return 0.0\n else\n return 2 * prod(gamma ∘ β, exponents(mono)) / gamma(sum(β, exponents(mono)))\n end\nend\nfunction disk_integral(mono::AbstractMonomial, r)\n d = degree(mono) + nvariables(mono)\n return circle_integral(mono) * r^d / d\nend\nfunction disk_integral(p::AbstractPolynomialLike, r)\n return sum(MultivariatePolynomials.coefficient(t) * disk_integral(monomial(t), r) for t in terms(p))\nend","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"The following function implements [KHJ14, (8)].","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"using SumOfSquares\nfunction outer_approximation(solver, d::Int, c; α = 1/2)\n @polyvar x[1:2]\n model = SOSModel(solver)\n r = escape_radius(c)\n S = @set sum(x.^2) <= r^2\n @variable(model, v, Poly(monomials(x, 0:2d)))\n @variable(model, w0, SOSPoly(monomials(x, 0:d)))\n @variable(model, w1, SOSPoly(monomials(x, 0:(d - 1))))\n @constraint(model, α * v(x => julia_map(x, c)) <= v, domain = S)\n w = w0 + w1 * (r^2 - sum(x.^2))\n @constraint(model, w >= v + 1, domain = S)\n @objective(model, Min, disk_integral(w, r))\n optimize!(model)\n if primal_status(model) == MOI.NO_SOLUTION\n return\n end\n return model\nend","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"The following function plots the Julia set with the outer approximation.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"using ImplicitPlots\nusing Plots\nfunction julia_plot(poly, c, n=200, m=1000; tol=1e-6, res = 1000)\n r = escape_radius(c)\n p = implicit_plot(poly; xlims=(-r, r) .* 1.1, ylims=(-r, r), resolution = res, label=\"\")\n θ = range(0, stop=2π, length=100)\n points = Vector{Float64}[]\n as = range(-r, r, length=n)\n bs = range(-r, r, length=n)\n for a in as, b in bs\n point = [a, b]\n if in_set(point, c, m)\n push!(points, point)\n end\n end\n xs = [point[1] for point in points]\n ys = [point[2] for point in points]\n scatter!(p, xs, ys, label=\"\", markerstrokewidth=0, markersize=1.5, m=:pixel)\n return p\nend","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"We need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"import CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"Let's start with the value of c corresponding to the left image of [KHJ14, Figure 3] and with degree 2.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"c = -0.7 + 0.2im\nmodel = outer_approximation(solver, 2, c)\nsolution_summary(model)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"We visualize below:","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"julia_plot(value(model[:v]), c)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"Let's now look at degree 4.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"model = outer_approximation(solver, 4, c)\nsolution_summary(model)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"We visualize below:","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"julia_plot(value(model[:v]), c)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"Let's now use the value of c corresponding to the right image of [KHJ14, Figure 3] and with degree 2.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"c = -0.9 + 0.2im\nmodel = outer_approximation(solver, 2, c)\nsolution_summary(model)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"We visualize below:","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"julia_plot(value(model[:v]), c)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"Let's now look at degree 4.","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"model = outer_approximation(solver, 4, c)\nsolution_summary(model)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"We visualize below:","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"julia_plot(value(model[:v]), c)","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"","category":"page"},{"location":"generated/Systems and Control/julia_set/","page":"Outer approximation of Julia set","title":"Outer approximation of Julia set","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"EditURL = \"../../tutorials/Noncommutative and Hermitian/noncommutative_variables.jl\"","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/#Noncommutative-variables","page":"Noncommutative variables","title":"Noncommutative variables","text":"","category":"section"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"(Image: ) (Image: ) Adapted from: Examples 2.11 and 2.2 of [BKP16]","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"[BKP16] Sabine Burgdorf, Igor Klep, and Janez Povh. Optimization of polynomials in non-commuting variables. Berlin: Springer, 2016.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/#Example-2.11","page":"Noncommutative variables","title":"Example 2.11","text":"","category":"section"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"We consider the Example 2.11 of [BKP16] in which the polynomial with noncommutative variables (x * y + x^2)^2 = x^4 + x^3y + xyx^2 + xyxy is tested to be sum-of-squares.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"using DynamicPolynomials\n@ncpolyvar x y\np = (x * y + x^2)^2","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"using SumOfSquares\nimport CSDP\noptimizer_constructor = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = Model(optimizer_constructor)\ncon_ref = @constraint(model, p in SOSCone())\n\noptimize!(model)","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"We see that both the monomials xy and yx are considered separately, this is a difference with the commutative version.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"certificate_basis(con_ref)","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"We see that the solution correctly uses the monomial xy instead of yx. We also identify that only the monomials x^2 and xy would be needed. This would be dectected by the Newton chip method of [Section 2.3, BKP16].","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"gram_matrix(con_ref).Q","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"When asking for the SOS decomposition, the numerically small entries makes the solution less readable.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"sos_decomposition(con_ref)","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"They are however easily discarded by using a nonzero tolerance:","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"sos_decomposition(con_ref, 1e-6)","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/#Example-2.2","page":"Noncommutative variables","title":"Example 2.2","text":"","category":"section"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"We consider now the Example 2.2 of [BKP16] in which the polynomial with noncommutative variables (x + x^10y^20x^10)^2 is tested to be sum-of-squares.","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"using DynamicPolynomials\n@ncpolyvar x y\nn = 10\np = (x + x^n * y^(2n) * x^n)^2\n\nusing SumOfSquares\nmodel = Model(optimizer_constructor)\ncon_ref = @constraint(model, p in SOSCone())\n\noptimize!(model)","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"Only two monomials were considered for the basis of the gram matrix thanks to the Augmented Newton chip method detailed in [Section 2.4, BKP16].","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"certificate_basis(con_ref)\n\ngram_matrix(con_ref).Q\n\nsos_decomposition(con_ref, 1e-6)","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"","category":"page"},{"location":"generated/Noncommutative and Hermitian/noncommutative_variables/","page":"Noncommutative variables","title":"Noncommutative variables","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"EditURL = \"../../tutorials/Polynomial Optimization/ellipsoid.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/#Exterior-of-ellipsoid","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"","category":"section"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"(Image: ) (Image: ) Adapted from: (Floudas et al., 1999; Section 3.5) and (Lasserre, 2009; Table 5.1)","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/#Introduction","page":"Exterior of ellipsoid","title":"Introduction","text":"","category":"section"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"Consider the polynomial optimization problem from (Floudas et al., 1999; Section 3.5)","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"A = [\n 0 0 1\n 0 -1 0\n -2 1 -1\n]\nbz = [3, 0, -4] - [0, -1, -6]\ny = [1.5, -0.5, -5]\n\nusing DynamicPolynomials\n@polyvar x[1:3]\np = -2x[1] + x[2] - x[3]\nusing SumOfSquares\ne = A * x - y\nf = e'e - bz'bz / 4\nK = @set sum(x) <= 4 && 3x[2] + x[3] <= 6 && f >= 0 && 0 <= x[1] && x[1] <= 2 && 0 <= x[2] && 0 <= x[3] && x[3] <= 3","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"import Clarabel\nsolver = Clarabel.Optimizer","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"function solve(d)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = K, maxdegree = d)\n optimize!(model)\n println(solution_summary(model))\n return model\nend","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"The first level of the hierarchy gives a lower bound of -7`","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"model2 = solve(2)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"The second level improves the lower bound","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"model4 = solve(4)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"The third level improves it even further","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"model6 = solve(6)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"The fourth level finds the optimal objective value as lower bound.","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"model8 = solve(8)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"","category":"page"},{"location":"generated/Polynomial Optimization/ellipsoid/","page":"Exterior of ellipsoid","title":"Exterior of ellipsoid","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"EditURL = \"../../tutorials/Polynomial Optimization/bilinear.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/#Bilinear-terms","page":"Bilinear terms","title":"Bilinear terms","text":"","category":"section"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"(Image: ) (Image: ) Adapted from: (Floudas et al., 1999; Section 3.1) and (Lasserre, 2009; Table 5.1)","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/#Introduction","page":"Bilinear terms","title":"Introduction","text":"","category":"section"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"Consider the polynomial optimization problem from (Floudas et al., 1999; Section 3.1).","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"using DynamicPolynomials\n@polyvar x[1:8]\np = sum(x[1:3])\nusing SumOfSquares\nK = @set 0.0025 * (x[4] + x[6]) <= 1 &&\n 0.0025 * (-x[4] + x[5] + x[7]) <= 1 &&\n 0.01 * (-x[5] + x[8]) <= 1 &&\n 100x[1] - x[1] * x[6] + 8333.33252x[4] <= 250000/3 &&\n x[2] * x[4] - x[2] * x[7] - 1250x[4] + 1250x[5] <= 0 &&\n x[3] * x[5] - x[3] * x[8] - 2500x[5] + 1250000 <= 0 &&\n 100 <= x[1] && x[1] <= 10000 &&\n 1000 <= x[2] && x[2] <= 10000 &&\n 1000 <= x[3] && x[3] <= 10000 &&\n 10 <= x[4] && x[4] <= 1000 &&\n 10 <= x[5] && x[5] <= 1000 &&\n 10 <= x[6] && x[6] <= 1000 &&\n 10 <= x[7] && x[7] <= 1000 &&\n 10 <= x[8] && x[8] <= 1000","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"import Clarabel\nsolver = Clarabel.Optimizer","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"function solve(d)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = K, maxdegree = d)\n optimize!(model)\n println(solution_summary(model))\n return model\nend","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"The first level of the hierarchy gives a lower bound of 2100","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"model2 = solve(2)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"","category":"page"},{"location":"generated/Polynomial Optimization/bilinear/","page":"Bilinear terms","title":"Bilinear terms","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"EditURL = \"../../tutorials/Extension/typed.jl\"","category":"page"},{"location":"generated/Extension/typed/#Multivariate-polynomials-implementations","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"","category":"section"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"The SumOfSquares package is built on top of the MultivariatePolynomials abstract interface. DynamicPolynomials is an implementation of this abstract interface so it can be used with SumOfSquares. Moreover, any other implementation can be used as well. To illustrate, we solve Examples 3.38 of [BPT12] with TypedPolynomials, another implementation of MultivariatePolynomials.","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"[BPT12] Blekherman, G. & Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"import TypedPolynomials\nTypedPolynomials.@polyvar x y\nusing SumOfSquares\nimport CSDP\nmodel = SOSModel(CSDP.Optimizer)\ncon_ref = @constraint(model, 2x^4 + 5y^4 - x^2*y^2 >= -2(x^3*y + x + 1))\noptimize!(model)\nsolution_summary(model)","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"We see that the problem is feasible. The Sum-of-Squares decomposition can be obtained as follows:","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"sos_decomposition(con_ref)","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"Why is there several implementations ? Depending in the use-case, one implementation may be more appropriate than another one. TypedPolynomials is faster than DynamicPolynomials but it requires new compilation whenever the list of variables changes. This means that TypedPolynomials is not appropriate when the number of variables is dynamic or too large. However, for a small number of variables, it can be faster. When solving Sum-of-Squares programs, the time is mostly taken by the Semidefinite programming solver. The time taken by SumOfSquares/JuMP/MathOptInterface are usually negligible or it time is taken by manipulation of JuMP or MathOptInterface functions therefore using TypedPolynomials over DynamicPolynomials may not make much difference in most cases.","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"One case for which using TypedPolynomials might be adequate is when using domain defined by equalities (possibly also with inequalities). Indeed, in that case, SumOfSquares computes the corresponding Gröbner basis which may take a non-negligible amount of time for large systems of equalities.","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"To illustrate this, consider the computation of Gröbner basis for the following system from [CLO05, p. 17]. The time taken by TypedPolynomials is below:","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"[CLO05] Cox, A. David & Little, John & O'Shea, Donal Using Algebraic Geometry. Graduate Texts in Mathematics, 2005. https://doi.org/10.1007/b138611","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"using BenchmarkTools\n@btime let\n TypedPolynomials.@polyvar x y\n S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y\n SemialgebraicSets.compute_gröbner_basis!(S.I)\nend","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"The time taken by DynamicPolynomials is as follows:","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"import DynamicPolynomials\n@btime let\n DynamicPolynomials.@polyvar x y\n S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y\n SemialgebraicSets.compute_gröbner_basis!(S.I)\nend","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"We see that TypedPolynomials is faster. The time is still negligible for this small system but for larger systems, choosing TypedPolynomials may be helpful. We can use this system in a Sum-of-Squares constraint as follows:","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"TypedPolynomials.@polyvar x y\nS = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y\npoly = -6x - 4y^3 + 2x*y^2 + 6x^3 - 3y^4 + 13x^2 * y^2\nmodel = Model(CSDP.Optimizer)\ncon_ref = @constraint(model, poly in SOSCone(), domain = S)\noptimize!(model)\nsolution_summary(model)","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"We obtain the following decomposition:","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"dec = sos_decomposition(con_ref, 1e-6)","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"We can verify that it is correct as follows:","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"rem(dec - poly, S.I)","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"Note that the difference between dec and poly is larger than between the full gram matrix because dec is obtained by dropping the lowest eigenvalues with the threshold 1e-6; see sos_decomposition.","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"rem(gram_matrix(con_ref) - poly, S.I)","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"","category":"page"},{"location":"generated/Extension/typed/","page":"Multivariate polynomials implementations","title":"Multivariate polynomials implementations","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"EditURL = \"../../tutorials/Polynomial Optimization/qcqp.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/#Nonconvex-quadratically-constrained-quadratic-programs","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"","category":"section"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"(Image: ) (Image: ) Adapted from: (Hesse, 1973), (Floudas et al., 1999; Section 3.4), (Laurent, 2008; Example 6.22) and (Lasserre, 2009; Table 5.1)","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"We consider the nonconvex Quadratically Constrained Quadratic Programs (QCQP) introduced in [H73]. Consider now the polynomial optimization problem (Laurent, 2008; Example 6.22) of maximizing the convex quadratic function (hence nonconvex since convex programs should either maximize concave functions or minimize convex functions) 25(x_1 - 2)^2 + (x_2 - 2)^2 + (x_3 - 1)^2 + (x_4 - 4)^2 + (x_5 - 1)^2 + (x_6 - 4)^2 over the basic semialgebraic set defined by the nonconvex quadratic inequalities (x_3 - 3)^2 + x_4 ge 4, (x_5 - 3)^2 + x_6 ge 4, and linear inequalities x_1 - 3x_2 le 2, -x_1 + x_2 le 2, 2 le x_1 + x_2 le 6, 0 le x_1 x_2, 1 le x_3 le 5, 0 le x_4 le 6, 1 le x_5 le 5, 0 le x_6 le 10, x_2 le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36 and the box constraints 0 le x_1 le 3 and 0 le x_2 le 4,","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"using DynamicPolynomials\n@polyvar x[1:6]\ncenters = [2, 2, 1, 4, 1, 4]\nweights = [25, 1, 1, 1, 1, 1]\np = -weights' * (x .- centers).^2\nusing SumOfSquares\nK = @set x[1] >= 0 && x[2] >= 0 &&\n x[3] >= 1 && x[3] <= 5 &&\n x[4] >= 0 && x[4] <= 6 &&\n x[5] >= 1 && x[5] <= 5 &&\n x[6] >= 0 && x[6] <= 10 &&\n (x[3] - 3)^2 + x[4] >= 4 &&\n (x[5] - 3)^2 + x[6] >= 4 &&\n x[1] - 3x[2] <= 2 &&\n -x[1] + x[2] <= 2 &&\n x[1] + x[2] <= 6 &&\n x[1] + x[2] >= 2","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"import Clarabel\nsolver = Clarabel.Optimizer","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"function solve(d)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = K, maxdegree = d)\n optimize!(model)\n println(solution_summary(model))\n return model\nend","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"The first level of the hierarchy cannot find any lower bound.","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"model2 = solve(2)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"The second level of the hierarchy finds the lower bound of -310.","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"model3 = solve(4)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"","category":"page"},{"location":"generated/Polynomial Optimization/qcqp/","page":"Nonconvex quadratically constrained quadratic programs","title":"Nonconvex quadratically constrained quadratic programs","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"EditURL = \"../../tutorials/Polynomial Optimization/goldstein_price.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/#Goldstein-price-function","page":"Goldstein-price function","title":"Goldstein-price function","text":"","category":"section"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"In this example, we consider the minimization of the Goldstein-price function.","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"using SumOfSquares\nusing DynamicPolynomials","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"Create symbolic variables (not JuMP decision variables)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"@polyvar x[1:2]","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"To use Sum-of-Squares Programming, we first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"import Clarabel\nusing Dualization\nmodel = SOSModel(dual_optimizer(Clarabel.Optimizer))","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"Create a JuMP decision variable for the lower bound","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"@variable(model, γ)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"f(x) is the Goldstein-Price function","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"f1 = x[1] + x[2] + 1\nf2 = 19 - 14*x[1] + 3*x[1]^2 - 14*x[2] + 6*x[1]*x[2] + 3*x[2]^2\nf3 = 2*x[1] - 3*x[2]\nf4 = 18 - 32*x[1] + 12*x[1]^2 + 48*x[2] - 36*x[1]*x[2] + 27*x[2]^2\nf = (1 + f1^2*f2) * (30 + f3^2*f4)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"Constraints f(x) - γ to be a sum of squares","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"con_ref = @constraint(model, f >= γ)\n@objective(model, Max, γ)\noptimize!(model)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"The lower bound found is 3","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"solution_summary(model)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"The moment matrix is as follows, we can already see the global minimizer [0, -1] from the entries (2, 1) and (3, 1). This heuristic way to obtain solutions to the polynomial optimization problem is suggested in (Laurent, 2008; (6.15)).","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"ν = moment_matrix(con_ref)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"Many entries of the matrix actually have the same moment. We can obtain the following list of these moments without duplicates (ignoring when difference of entries representing the same moments is below 1e-5)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"μ = measure(ν, atol = 1e-5)","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"The truncated moment matrix can then be obtained as follows","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"ν_truncated = moment_matrix(μ, monomials(x, 0:3))","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"Let's check if the flatness property is satisfied. The rank of ν_truncated seems to be 1:","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"using LinearAlgebra\nLinearAlgebra.svdvals(Matrix(ν_truncated.Q))\nLinearAlgebra.rank(Matrix(ν_truncated.Q), rtol = 1e-3)\nsvdvals(Matrix(ν_truncated.Q))","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"The rank of ν is clearly higher than 1, closer to 3:","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"svdvals(Matrix(ν.Q))","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"Even if the flatness property is not satisfied, we can still try extracting the minimizer with a low rank decomposition of rank 3. We find the optimal solution again doing so:","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"atomic_measure(ν, FixedRank(3))","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"","category":"page"},{"location":"generated/Polynomial Optimization/goldstein_price/","page":"Goldstein-price function","title":"Goldstein-price function","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"EditURL = \"../../tutorials/Getting started/sum-of-squares_matrices.jl\"","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/#Sum-of-Squares-matrices","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"","category":"section"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"(Image: ) (Image: ) Adapted from: Examples 3.77 of [BPT12]","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/#Introduction","page":"Sum-of-Squares matrices","title":"Introduction","text":"","category":"section"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"Consider the symmetric polynomial matrix P(x) = beginbmatrix x^2 - 2x + 2 x\n x x^2 endbmatrix We could like to know whether P(x) is positive semidefinite for all x in mathbbR.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"using DynamicPolynomials\n@polyvar x\nP = [x^2 - 2x + 2 x\n x x^2]","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"A sufficient condition for a symmetric polynomial matrix P(x) to be positive semidefinite for all x is to the existence of a matrix M(x) such that P(x) = M^top(x) M(x). If such matrix M exists, we say that the matrix is an \\emph{sos matrix} (see [Definition 3.76, BPT13]). While determining whether P(x) is positive semidefinite for all x, is NP-hard (checking nonnegativity of a polynomial is reduced to this problem for 1 times 1 matrices), checking whether P(x) is an sos matrix is an sos program.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"using SumOfSquares","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"import CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n\nmodel = SOSModel(solver)\nmat_cref = @constraint(model, P in PSDCone())\noptimize!(model)\ntermination_status(model)","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"While the reformulation of sos matrix to sos polynomial is rather simple, as explained in the \"Sum-of-Squares reformulation\" section below, there is a technical subtelty about the Newton polytope that if not handled correctly may result in an SDP of large size with bad numerical behavior. For this reason, it is recommended to model sos matrix constraints as such as will be shown in this notebook and not do the formulation manually unless there is a specific reason to do so.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"As we can verify as follows, only 3 monomials are used using the sos matrix constraint.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"certificate_monomials(mat_cref)","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/#Sum-of-Squares-reformulation","page":"Sum-of-Squares matrices","title":"Sum-of-Squares reformulation","text":"","category":"section"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"One way to obtain the reduction to an sos program is to create an intermediate vector of variable y and check whether the polynomial p(x y) = y^top P(x) y is sos. However, special care is required when approximating the Newton polytope of p(x y). Indeed, for instance if the entries of P(x) are quadratic forms then the Newton polytope of p(x y) is the cartesian product between the Newton polytope of y^top y and the Newton polytope of x^top x. In other words, p(x y) belongs to a family of quartic forms called biquadratic forms. This fact is important when generating the semidefinite program so that only bilinear monomials are used. So if the cheap outer approximation is used (instead of the exact polyhedral computation) for the newton polytope then it is important to use a multipartite computation approximation of the newton polytope. The multipartie exact approach may perform worse compared to the unipartite exact in certain cases though. Consider for instance the polynomial matrix mathrmDiag(x_1^1 x_2^2) for which p(x y) = x_1^2y_1^2 + x_2^2y_2^2. For this polynomial, only the monomials x_1y_1 and x_2y_2 are needed in the SDP reformulation while the multipartite approach, as it will compute the Newton polytope as a cartesian product, will not see the dependence between x and y in the presence of monomials and will also select the monomials x_1y_2 and x_2y_1.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"@polyvar y[1:2]\np = vec(y)' * P * vec(y)","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"We can see above that p is biquadratic polynomial in the variables x and y. Computing the Newton polytope with the cheap outer approximation without exploiting this multipartite structure gives the following 6 monomials.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"X = monomials(p)\nunipartite = Certificate.NewtonDegreeBounds(tuple())\nCertificate.monomials_half_newton_polytope(X, unipartite)","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"Exploiting the multipartite structure gives 4 monomials.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"multipartite = Certificate.NewtonDegreeBounds(([x], y))\nCertificate.monomials_half_newton_polytope(X, multipartite)","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"In the example above, there were only 3 monomials, where does the difference come from ? Using the monomial basis, the only product of two monomials that is equal to y[2]^2 is y[2] * y[2]. As y[2]^2 is not a monomial of p, we can conclude that the diagonal entry with row and column corresponding to y[2] will be zero hence the whole column and row will be zero as well. Therefore, we can remove this monomial.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(multipartite))","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"The same reasoning can be used for monomials y[1]y[2] and x therefore whether we exploit the multipartite structure or not, we get only 3 monomials thanks to this post filter.","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(unipartite))","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"","category":"page"},{"location":"generated/Getting started/sum-of-squares_matrices/","page":"Sum-of-Squares matrices","title":"Sum-of-Squares matrices","text":"This page was generated using Literate.jl.","category":"page"},{"location":"sumofsquares/#Sum-of-Squares-Programming","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"","category":"section"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"This section contains a brief introduction to Sum-of-Squares Programming. For more details, see [BPT12, Las09, Lau09].","category":"page"},{"location":"sumofsquares/#Quadratic-forms-and-Semidefinite-programming","page":"Sum-of-Squares Programming","title":"Quadratic forms and Semidefinite programming","text":"","category":"section"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"The positive semidefiniteness of a n times n real symmetric matrix Q is equivalent to the nonnegativity of the quadratic form p(x) = x^top Q x for all vector x in mathbbR^n. For instance, the polynomial","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"x_1^2 + 2x_1x_2 + 5x_2^2 + 4x_2x_3 + x_3^2 = x^top beginpmatrix1 1 01 5 2 0 2 1endpmatrix x","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"is nonnegative since the matrix of the right-hand side is positive semidefinite. Moreover, a certificate of nonnegativity can be extracted from the Cholesky decomposition of the matrix:","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"(x_1 + x_2)^2 + (2x_2 + x_3)^2 = x^top beginpmatrix1 1 00 2 1endpmatrix^top beginpmatrix1 1 00 2 1endpmatrix x","category":"page"},{"location":"sumofsquares/#Polynomial-nonnegativity-and-Semidefinite-programming","page":"Sum-of-Squares Programming","title":"Polynomial nonnegativity and Semidefinite programming","text":"","category":"section"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"This can be generalized to a polynomial of arbitrary degree. A polynomial p(x) is nonnegative if it can be rewritten as p(x) = X^top Q X where Q is a real symmetric positive semidefinite matrix and X is a vector of monomials.","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"For instance","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"x_1^2 + 2x_1^2x_2 + 5x_1^2x_2^2 + 4x_1x_2^2 + x_2^2 = X^top beginpmatrix1 1 01 5 2 0 2 1endpmatrix X","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"where X = (x_1 x_1x_2 x_2) Similarly to the previous section, the Cholesky factorization of the matrix can be used to extract a sum of squares certificate of nonnegativity for the polynomial:","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"(x_1 + x_1x_2)^2 + (2x_1x_2 + x_2)^2 = X^top beginpmatrix1 1 00 2 1endpmatrix^top beginpmatrix1 1 00 2 1endpmatrix X","category":"page"},{"location":"sumofsquares/#When-is-nonnegativity-equivalent-to-sum-of-squares-?","page":"Sum-of-Squares Programming","title":"When is nonnegativity equivalent to sum of squares ?","text":"","category":"section"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"Determining whether a polynomial is nonnegative is NP-hard. The condition of the previous section was only sufficient, that is, there exists nonnegative polynomials that are not sums of squares. Hilbert showed in 1888 that there are exactly 3 cases for which there is equivalence between the nonnegativity of the polynomials of n variables and degree 2d and the existence of a sum of squares decomposition.","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"n = 1 : Univariate polynomials\n2d = 2 : Quadratic polynomials\nn = 2, 2d = 4 : Bivariate quartics","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"The first explicit example of polynomial that was not a sum of squares was given by Motzkin in 1967:","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"x_1^4x_2^2 + x_1^2x_2^4 + 1 - 3x_1^2x_2^2 geq 0 quad forall x","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"While it is not a sum of squares, it can still be certified to be nonnegative using sum-of-squares programming by identifying it with a rational sum-of-squares decomposition. These facts can be verified numerically using this package as detailed in the Motzkin example.","category":"page"},{"location":"sumofsquares/#References","page":"Sum-of-Squares Programming","title":"References","text":"","category":"section"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"sumofsquares/","page":"Sum-of-Squares Programming","title":"Sum-of-Squares Programming","text":"[Lau09] Laurent, M. Sums of squares, moment matrices and optimization over polynomials Emerging applications of algebraic geometry, Springer, 2009, 157-270.","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"EditURL = \"../../tutorials/Getting started/getting_started.jl\"","category":"page"},{"location":"generated/Getting started/getting_started/#Getting-started","page":"Getting started","title":"Getting started","text":"","category":"section"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"(Image: ) (Image: ) Adapted from: SOSTOOLS' SOSDEMO1 (See Section 4.1 of SOSTOOLS User's Manual) and Example 2.4 of [PJ08]","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"P. Parrilo and A. Jadbabaie Approximation of the joint spectral radius using sum of squares. Linear Algebra and its Applications, Elsevier (2008), 428, 2385-2402","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"using DynamicPolynomials\n@polyvar x y\np = 2*x^4 + 2*x^3*y - x^2*y^2 + 5*y^4","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"using SumOfSquares\nimport CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = SOSModel(solver)\ncon_ref = @constraint(model, p >= 0)\noptimize!(model)\nprimal_status(model)","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"We see above that the solver found a feasible solution. We now inspect this solution:","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"q = gram_matrix(con_ref)","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"We can get the SOS decomposition from the gram matrix as follows:","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"sosdec = SOSDecomposition(q)","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"We now seek for the SOS decomposition of the following polynomial:","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"p = 4*x^4*y^6 + x^2 - x*y^2 + y^2","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"We build the same model as previously with this new polynomial. Here we can use Model instead of SOSModel as we explicitly constrain p to belong to the SOS cone with p in SOSCone().","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"model = Model(solver)\ncon_ref = @constraint(model, p in SOSCone())\noptimize!(model)\nprimal_status(model)","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"We can query the SOS decomposition directly from the constraint reference as follows:","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"sos_decomposition(con_ref)","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"","category":"page"},{"location":"generated/Getting started/getting_started/","page":"Getting started","title":"Getting started","text":"This page was generated using Literate.jl.","category":"page"},{"location":"constraints/#Constraints","page":"Constraints","title":"Constraints","text":"","category":"section"},{"location":"constraints/#Equality-constraints-between-polynomials","page":"Constraints","title":"Equality constraints between polynomials","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Equality between polynomials in PolyJuMP uses the same syntax as equality between affine or quadratic expression in JuMP. For instance, creating two quadratic n-variate polynomials p and q that must sum up to one can be done as follows:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> n = 3\n3\n\njulia> using DynamicPolynomials\n\njulia> @polyvar x[1:n]\n(Variable{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}[x₁, x₂, x₃],)\n\njulia> X = monomials(x, 0:2)\n10-element MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}:\n 1\n x₃\n x₂\n x₁\n x₃²\n x₂x₃\n x₂²\n x₁x₃\n x₁x₂\n x₁²\n\njulia> using SumOfSquares\n\njulia> model = Model()\nA JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: NO_OPTIMIZER\nSolver name: No optimizer attached.\n\njulia> @variable(model, p, Poly(X))\n(_[1]) + (_[2])x₃ + (_[3])x₂ + (_[4])x₁ + (_[5])x₃² + (_[6])x₂x₃ + (_[7])x₂² + (_[8])x₁x₃ + (_[9])x₁x₂ + (_[10])x₁²\n\njulia> @variable(model, q, Poly(X))\n(_[11]) + (_[12])x₃ + (_[13])x₂ + (_[14])x₁ + (_[15])x₃² + (_[16])x₂x₃ + (_[17])x₂² + (_[18])x₁x₃ + (_[19])x₁x₂ + (_[20])x₁²\n\njulia> @constraint(model, p + q == 1)\n(_[1] + _[11] - 1) + (_[2] + _[12])x₃ + (_[3] + _[13])x₂ + (_[4] + _[14])x₁ + (_[5] + _[15])x₃² + (_[6] + _[16])x₂x₃ + (_[7] + _[17])x₂² + (_[8] + _[18])x₁x₃ + (_[9] + _[19])x₁x₂ + (_[10] + _[20])x₁² ∈ PolyJuMP.ZeroPoly()","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Vectorized constraints can also be used as well as vector of constraints, named constraints, ... For instance, if P and Q are two n times n matrices of polynomials, the following constraints the sum of rows and columns to match:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"@constraint(model, con[i=1:n], sum(P[i, :]) == sum(Q[:, i]))","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"and con[i] contains the reference to the constraint between the ith row of P and the ith column of Q.","category":"page"},{"location":"constraints/#Inequality-constraints-between-polynomials","page":"Constraints","title":"Inequality constraints between polynomials","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Polynomials can be constrained to be sum-of-squares with the in syntax. For instance, to constrain a polynomial p to be sum-of-squares, do","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> @constraint(model, p in SOSCone())\n(_[1]) + (_[2])x₃ + (_[3])x₂ + (_[4])x₁ + (_[5])x₃² + (_[6])x₂x₃ + (_[7])x₂² + (_[8])x₁x₃ + (_[9])x₁x₂ + (_[10])x₁² is SOS","category":"page"},{"location":"constraints/#Automatically-interpreting-polynomial-nonnegativity-as-a-sum-of-squares-constraint","page":"Constraints","title":"Automatically interpreting polynomial nonnegativity as a sum-of-squares constraint","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"As detailed in When is nonnegativity equivalent to sum of squares ?, the nonnegativity of a polynomial is not equivalent to the existence of a sum-of-squares decomposition. However, if explicitely specified, nonnegativity constraints can be automatically interpreted as sum-of-squares constraints. The simplest way to do that is to create the model with","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"model = SOSModel(...)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"instead of","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"model = Model(...)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"An alternative equivalent way is to call setpolymodule! after creating the model:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> setpolymodule!(model, SumOfSquares)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"This second approach may be useful if the SumOfSquares JuMP extension need to be used with another JuMP extension that also has a special model constructor. A third alternative is the following:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> PolyJuMP.setdefault!(model, PolyJuMP.NonNegPoly, SOSCone)\nSOSCone (alias for NonnegPolyInnerCone{MathOptInterface.PositiveSemidefiniteConeTriangle})\n\njulia> PolyJuMP.setdefault!(model, PolyJuMP.PosDefPolyMatrix, SOSMatrixCone)\nSOSMatrixCone (alias for PSDMatrixInnerCone{MathOptInterface.PositiveSemidefiniteConeTriangle})","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"This approach adds the flexibility to choose the default cone for","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"constraints of the form @constraint(mode, ..., some_polynomial ≥ other_polynomial, ...) which is the cone given as default to PolyJuMP.NonNegPoly; and\nconstraints of the form @constraint(mode, ..., some_matrix_of_polynomial in PSDCone(), ...) or @constraint(mode, ..., some_matrix_of_polynomial >= other_matrix_of_polynomial, PSDCone(), ...) which is the cone given as default to PolyJuMP.NonNegPolyMatrix.","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"For instance, to use the diagonally-dominant-sum-of-squares cone (see [Definition 2, AM17]) for the first type of contraints, do","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> PolyJuMP.setdefault!(model, PolyJuMP.NonNegPoly, DSOSCone)\nDSOSCone (alias for NonnegPolyInnerCone{SumOfSquares.DiagonallyDominantConeTriangle})","category":"page"},{"location":"constraints/#Changing-the-polynomial-basis","page":"Constraints","title":"Changing the polynomial basis","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"As introduced in Choosing a polynomial basis, there may be numerical advantages to use another basis than the standard monomial basis when creating polynomial variables. Similarly, other polynomial bases can be used for polynomial constraints. However, for constraints, the polynomial space is determined by the polynomial constrained to be nonnegative. For instance, consider the constraint:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> using DynamicPolynomials\n\njulia> @polyvar x y\n(x, y)\n\njulia> using SumOfSquares\n\njulia> model = SOSModel()\nA JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: NO_OPTIMIZER\nSolver name: No optimizer attached.\n\njulia> @variable(model, α)\nα\n\njulia> @variable(model, β)\nβ\n\njulia> @constraint(model, α * x^2 + β * y^2 ≥ (α - β) * x * y)\n(β)y² + (-α + β)xy + (α)x² is SOS","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"where α and β are JuMP decision variables and x and y are polynomial variables. Since the polynomial is a quadratic form, the sum-of-squares certificate is also a quadratic form (see [Section~3.3.4, BPT12]). Hence the default polynomial basis used for the [Nonnegative polynomial variables] certificate is MonomialBasis([x, y]), that is, we search for a positive semidefinite matrix Q such that","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"alpha x^2 + beta y^2 - (alpha - beta) x y = X^top Q X","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"where X = (x y).","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"As the polynomial space is determined by the polynomial being constrained, only the basis type needs to be given. For instance, to use the scaled monomial basis in the example above, use","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> @constraint(model, α * x^2 + β * y^2 ≥ (α - β) * x * y, basis = ScaledMonomialBasis)\n(β)y² + (-α + β)xy + (α)x² is SOS","category":"page"},{"location":"constraints/#Polynomial-nonnegativity-on-a-subset-of-the-space","page":"Constraints","title":"Polynomial nonnegativity on a subset of the space","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"By default, the constraint","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> @constraint(model, x^3 - x^2 + 2x*y -y^2 + y^3 >= α)\n(-α) + (-1)y² + (2)xy + (-1)x² + (1)y³ + (1)x³ is SOS","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"constrains the polynomial to be nonnegative for every real numbers x and y. However, the set of points (x, y) for which the polynomial is constrained to be nonnegative can be specified by the domain keyword:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"julia> S = @set x >= 0 && y >= 0 && x + y >= 1;\n\njulia> @constraint(model, x^3 - x^2 + 2x*y -y^2 + y^3 >= α, domain = S)\n(-α) + (-1)y² + (2)xy + (-1)x² + (1)y³ + (1)x³ is SOS","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"See this notebook for a detailed example.","category":"page"},{"location":"constraints/#Dual-of-polynomial-constraints","page":"Constraints","title":"Dual of polynomial constraints","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"The dual of a polynomial constraint cref is a moment serie μ as defined in MultivariateMoments. The dual can be obtained with the dual function as with classical dual values in JuMP.","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"μ = dual(cref)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"By dual of a Sum-of-Squares constraint, we may mean different things and the meaning chosen for dual function was chosen for consistency with the definition of the JuMP dual function to ensure that generic code will work as expected with Sum-of-Squares constraints. In a Sum-of-Squares constraint, a polynomial p is constraint to be SOS in some domain defined by polynomial q_i. So p(x) is constrained to be equal to s(x) = s_0(x) + s_1(x) * q_1(x) + s_2(x) * q_2(x) + ... where the s_i(x) polynomials are Sum-of-Squares. The dual of the equality constraint between p(x) and s(x) is given by SumOfSquares.MultivariateMoments.moments.","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"μ = moments(cref)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Note that the dual and moments may give different results. For instance, the output of dual only contains the moments corresponding to monomials of p while the output of moments may give the moments of other monomials if s(x) has more monomials than p(x). Besides, if the domain contains polynomial, equalities, only the remainder of p(x) - s(x) modulo the ideal is constrained to be zero, see Corollary 2 of [CLO13]. In that case, the output moments is the dual of the constraint on the remainder so some monomials may have different moments with dual or moments.","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"The dual of the Sum-of-Squares constraint on s_0(x), commonly referred to as the the matrix of moments can be obtained using moment_matrix:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"ν = moment_matrix(cref)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"The atomic_measure function of MultivariateMoments can be used to check if there exists an atomic measure (i.e. a measure that is a sum of Dirac measures) that has the moments given in the the moment matrix ν. This can be used for instance in polynomial optimization (see this notebook) or stability analysis (see this notebook).","category":"page"},{"location":"constraints/#References","page":"Constraints","title":"References","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"[CLO13] Cox, D., Little, J., & OShea, D. Ideals, varieties, and algorithms: an introduction to computational algebraic geometry and commutative algebra. Springer Science & Business Media, 2013.","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization. ArXiv e-prints, 2017.","category":"page"},{"location":"constraints/#API-Reference","page":"Constraints","title":"API Reference","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Default choice for the maxdegree keyword:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.default_maxdegree","category":"page"},{"location":"constraints/#SumOfSquares.default_maxdegree","page":"Constraints","title":"SumOfSquares.default_maxdegree","text":"default_maxdegree(monos, domain)\n\nReturn the default maxdegree to use for certifying a polynomial with monomials monos to be Sum-of-Squares over the domain domain. By default, the maximum of the maxdegree of monos and of all multipliers of the domain are used so that at least constant multipliers can be used with a Putinar certificate.\n\n\n\n\n\n","category":"function"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Special case that is second-order cone representable:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.PositiveSemidefinite2x2ConeTriangle","category":"page"},{"location":"constraints/#SumOfSquares.PositiveSemidefinite2x2ConeTriangle","page":"Constraints","title":"SumOfSquares.PositiveSemidefinite2x2ConeTriangle","text":"struct PositiveSemidefinite2x2ConeTriangle <: MOI.AbstractSymmetricMatrixSetTriangle end\n\nCone of positive semidefinite matrices of 2 rows and 2 columns.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Inner approximations of the PSD cone that do not require semidefinite programming:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.DiagonallyDominantConeTriangle\nSumOfSquares.ScaledDiagonallyDominantConeTriangle","category":"page"},{"location":"constraints/#SumOfSquares.DiagonallyDominantConeTriangle","page":"Constraints","title":"SumOfSquares.DiagonallyDominantConeTriangle","text":"struct DiagonallyDominantConeTriangle <: MOI.AbstractSymmetricMatrixSetTriangle\n side_dimension::Int\nend\n\nSee Definition 4 of [AM17] for a precise definition of the last two items.\n\n[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.ScaledDiagonallyDominantConeTriangle","page":"Constraints","title":"SumOfSquares.ScaledDiagonallyDominantConeTriangle","text":"struct ScaledDiagonallyDominantConeTriangle <: MOI.AbstractSymmetricMatrixSetTriangle\n side_dimension::Int\nend\n\nSee Definition 4 of [AM17] for a precise definition of the last two items.\n\n[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Approximations of the cone of nonnegative polynomials:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.NonnegPolyInnerCone\nSumOfSquares.SOSCone\nSumOfSquares.SDSOSCone\nSumOfSquares.DSOSCone","category":"page"},{"location":"constraints/#SumOfSquares.NonnegPolyInnerCone","page":"Constraints","title":"SumOfSquares.NonnegPolyInnerCone","text":"struct NonnegPolyInnerCone{MCT <: MOI.AbstractVectorSet}\nend\n\nInner approximation of the cone of nonnegative polynomials defined by the set of polynomials of the form\n\nX^\\top Q X\n\nwhere X is a vector of monomials and Q is a symmetric matrix that belongs to the cone psd_inner.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.SOSCone","page":"Constraints","title":"SumOfSquares.SOSCone","text":"const SOSCone = NonnegPolyInnerCone{MOI.PositiveSemidefiniteConeTriangle}\n\nSum-of-squares cone; see NonnegPolyInnerCone.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.SDSOSCone","page":"Constraints","title":"SumOfSquares.SDSOSCone","text":"const SDSOSCone = NonnegPolyInnerCone{ScaledDiagonallyDominantConeTriangle}\n\nScaled-diagonally-dominant-sum-of-squares cone; see [Definition 2, AM17] and NonnegPolyInnerCone.\n\n[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.DSOSCone","page":"Constraints","title":"SumOfSquares.DSOSCone","text":"const DSOSCone = NonnegPolyInnerCone{DiagonallyDominantConeTriangle}\n\nDiagonally-dominant-sum-of-squares cone; see [Definition 2, AM17] and NonnegPolyInnerCone.\n\n[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Approximations of the cone of positive semidefinite polynomial matrices:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.PSDMatrixInnerCone\nSumOfSquares.SOSMatrixCone","category":"page"},{"location":"constraints/#SumOfSquares.PSDMatrixInnerCone","page":"Constraints","title":"SumOfSquares.PSDMatrixInnerCone","text":"struct PSDMatrixInnerCone{MCT <: MOI.AbstractVectorSet} <: PolyJuMP.PolynomialSet\nend\n\nInner approximation of the cone of polynomial matrices P(x) that are positive semidefinite for any x defined by the set of n times n polynomial matrices such that the polynomial y^top P(x) y belongs to NonnegPolyInnerCone{MCT} where y is a vector of n auxiliary polynomial variables.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.SOSMatrixCone","page":"Constraints","title":"SumOfSquares.SOSMatrixCone","text":"const SOSMatrixCone = PSDMatrixInnerCone{MOI.PositiveSemidefiniteConeTriangle}\n\nSum-of-squares matrices cone; see [Section 3.3.2, BPT12] and PSDMatrixInnerCone.\n\n[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Approximations of the cone of convex polynomials:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.ConvexPolyInnerCone\nSumOfSquares.SOSConvexCone","category":"page"},{"location":"constraints/#SumOfSquares.ConvexPolyInnerCone","page":"Constraints","title":"SumOfSquares.ConvexPolyInnerCone","text":"struct ConvexPolyInnerCone{MCT} <: PolyJuMP.PolynomialSet end\n\nInner approximation of the set of convex polynomials defined by the set of polynomials such that their hessian belongs to to the set PSDMatrixInnerCone{MCT}()\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.SOSConvexCone","page":"Constraints","title":"SumOfSquares.SOSConvexCone","text":"const SOSConvexCone = ConvexPolyInnerCone{MOI.PositiveSemidefiniteConeTriangle}\n\nSum-of-squares convex polynomials cone; see [Section 3.3.3, BPT12] and ConvexPolyInnerCone.\n\n[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Approximations of the cone of copositive matrices:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.CopositiveInner","category":"page"},{"location":"constraints/#SumOfSquares.CopositiveInner","page":"Constraints","title":"SumOfSquares.CopositiveInner","text":"struct CopositiveInner{S} <: PolyJuMP.PolynomialSet\n # Inner approximation of the PSD cone, i.e. typically either\n # `SOSCone`, `DSOSCone` or `SDSOSCone`,\n psd_inner::S\nend\n\nA symmetric matrix Q is copositive if x^top Q x ge 0 for all vector x in the nonnegative orthant. Checking copositivity is a co-NP-complete problem [MK87] and this cone is only the inner approximation of the cone of copositive symmetric matrices given by Minknowski sum of psd_inner and the cone of symmetric matrices with nonnegative entries (the diagonal entries can be chosen to be zero) [Lemma 3.164, BPT12].\n\nThe matrix with nonnegative entries can be interpreted as lagrangian multipliers. For instance,\n\n@polyvar x y\n@constraint(model, x^2 - 2x*y + y^2 in CopositiveInner(SOSCone()))\n\nis equivalent to\n\n# Matrix that we require to be copositive\nQ = [ 1 -1\n -1 1]\nλ = @variable(model, lower_bound=0)\n# Symmetric matrix of nonnegative entries\nΛ = [0 λ\n λ 0]\nusing LinearAlgebra # For `Symmetric`\n@constraint(model, Symmetric(Q - Λ) in PSDCone())\n\nwhich is equivalent to\n\n@polyvar x y\nλ = @variable(model, lower_bound=0)\n@constraint(model, x^2 - 2x*y + y^2 - 2*λ * x*y in SOSCone())\n\nwhich is the same as, using the domain keyword,\n\n@polyvar x y\n@constraint(model, x^2 - 2x*y + y^2 in SOSCone(), domain = @set x*y ≥ 0)\n\nAs an important difference with its equivalent forms, the GramMatrixAttribute for the copositive constraint is given by matrix Q while for the equivalent form using the domainkeyword, the value of the attribute would correspond to the the gram matrix in thepsd_innercone, i.e. which should be equal toQ - Λ`.\n\n[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.\n\n[MK87] K. G. Murty and S. N. Kabadi. Some NP-complete problems in quadratic and nonlinear programming. Mathematical programming, 39:117–129, 1987.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Types of sparsity","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.Certificate.Sparsity.Variable\nSumOfSquares.Certificate.Sparsity.Monomial\nSumOfSquares.Certificate.Sparsity.SignSymmetry\nSumOfSquares.Certificate.Sparsity.XORSpace","category":"page"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.Variable","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.Variable","text":"struct Sparsity.Variable <: Sparsity.Pattern end\n\nVariable or correlative sparsity as developed in [WSMM06].\n\n[WSMM06] Waki, Hayato, Sunyoung Kim, Masakazu Kojima, and Masakazu Muramatsu. \"Sums of squares and semidefinite program relaxations for polynomial optimization problems with structured sparsity.\" SIAM Journal on Optimization 17, no. 1 (2006): 218-242.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.Monomial","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.Monomial","text":"struct Sparsity.Monomial{C<:CEG.AbstractCompletion} <: Sparsity.Pattern\n completion::C\n k::Int\n use_all_monomials::Bool\nend\n\nMonomial or term sparsity as developed in [WML20a, WML20b]. The completion field should be ClusterCompletion() [default] for the block-closure or cluster completion [WML20a], and ChordalCompletion() for chordal completion [WML20b]. The integer k [default=0] corresponds to Σ_k defined in [(3.2), WML20a] and k = 0 corresponds to Σ_* defined in [(3.3), WML20a]. If use_all_monomials is false then some monomials of the basis might be dropped from the basis if not needed.\n\n[WML20a] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. TSSOS: A Moment-SOS hierarchy that exploits term sparsity. arXiv preprint arXiv:1912.08899 (2020).\n\n[WML20b] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension. arXiv preprint arXiv:2003.03210 (2020).\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.SignSymmetry","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.SignSymmetry","text":"struct SignSymmetry <: Sparsity.Pattern end\n\nSign symmetry as developed in [Section III.C, L09]. Let n be the number of variables. A sign-symmetry is a binary vector r of {0, 1}^n such that dot(r, e) is even for all exponent e.\n\nLet o(e) be the binary vector of {0, 1}^n for which the ith bit is i iff the ith entry of e is odd. Let O be the set of o(e) for exponents of e. A binary vector r is a sign-symmetry if an only if it is orthogonal to all the elements of O.\n\nSince we are only interested in the orthogonal subspace, say R, of O, even if O is not a linear subspace (i.e., it is not invariant under xor), we compute its span. We start by creating row echelon form of the span of O using XORSpace. We then compute a basis for R. The set R of sign symmetries will be the span of this basis.\n\nLet a, b be exponents of monomials of the gram basis. For any r in R,\n\n⟨r, o(a + b)⟩ = ⟨r, xor(o(a), o(b)⟩ = xor(⟨r, o(a)⟩, ⟨r, o(b)⟩)\n\nFor o(a, b) to be sign symmetric, this scalar product should be zero for all sign symmetry r. This is equivalent to saying that ⟨r, o(a)⟩ and ⟨r, o(b)⟩ are equal for all r in R. In other words, the projection of o(a) and o(b) to R have the same coordinates in the basis. If we order the monomials by grouping them by equal coordinates of projection, we see that the product that are sign symmetric form a block diagonal structure. This means that we can group the monomials by these coordinates.\n\n[L09] Löfberg, Johan. Pre-and post-processing sum-of-squares programs in practice. IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.XORSpace","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.XORSpace","text":"mutable struct XORSpace{T<:Integer}\n dimension::Int\n basis::Vector{T}\nend\n\nBasis for a linear subspace of the Hamming space (i.e. set of binary string {0, 1}^n of length n) represented in the bits of an integer of type T. This is used to implement Certificate.Sparsity.SignSymmetry.\n\nConsider the scalar product ⟨a, b⟩ which returns the the xor of the bits of a & b. It is a scalar product since ⟨a, b⟩ = ⟨b, a⟩ and ⟨a, xor(b, c)⟩ = xor(⟨a, b⟩, ⟨a, c⟩).\n\nWe have two options here to compute the orthogonal space.\n\nThe first one is to build an orthogonal basis with some kind of Gram-Schmidt process and then to obtain the orthogonal space by removing the projection from each vector of the basis.\n\nThe second option, which is the one we use here is to compute the row echelon form and then read out the orthogonal subspace directly from it. For instance, if the row echelon form is\n\n1 a 0 c e\n b 1 d f\n\nthen the orthogonal basis is\n\na 1 b 0 0\nc 0 d 1 0\ne 0 f 0 1\n\nThe basis vector has dimension nonzero elements. Any element added with push! can be obtained as the xor of some of the elements of basis. Moreover, the basis is kept in row echelon form in the sense that the first, second, ..., i - 1th bits of basis[i] are zero and basis[i] is zero if its ith bit is not one.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Ideal certificates:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.Certificate.MaxDegree\nSumOfSquares.Certificate.FixedBasis\nSumOfSquares.Certificate.Newton\nSumOfSquares.Certificate.Remainder\nSumOfSquares.Certificate.Sparsity.Ideal\nSumOfSquares.Certificate.Symmetry.Ideal","category":"page"},{"location":"constraints/#SumOfSquares.Certificate.MaxDegree","page":"Constraints","title":"SumOfSquares.Certificate.MaxDegree","text":"struct MaxDegree{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: SimpleIdealCertificate{CT, BT}\n cone::CT\n basis::Type{BT}\n maxdegree::Int\nend\n\nThe MaxDegree certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by exhibiting a Sum-of-Squares polynomials σ(x) such that p(x) - σ(x) is guaranteed to be zero for all x such that h_i(x) = 0. The polynomial σ(x) is search over cone with a basis of type basis such that the degree of σ(x) does not exceed maxdegree.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.FixedBasis","page":"Constraints","title":"SumOfSquares.Certificate.FixedBasis","text":"struct FixedBasis{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis} <: SimpleIdealCertificate{CT, BT}\n cone::CT\n basis::BT\nend\n\nThe FixedBasis certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by exhibiting a Sum-of-Squares polynomials σ(x) such that p(x) - σ(x) is guaranteed to be zero for all x such that h_i(x) = 0. The polynomial σ(x) is search over cone with basis basis.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Newton","page":"Constraints","title":"SumOfSquares.Certificate.Newton","text":"struct Newton{CT <: SumOfSquares.SOSLikeCone, BT <: MB.AbstractPolynomialBasis, NPT <: Tuple} <: SimpleIdealCertificate{CT, BT}\n cone::CT\n basis::Type{BT}\n variable_groups::NPT\nend\n\nThe Newton certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by exhibiting a Sum-of-Squares polynomials σ(x) such that p(x) - σ(x) is guaranteed to be zero for all x such that h_i(x) = 0. The polynomial σ(x) is search over cone with a basis of type basis chosen using the multipartite Newton polytope with parts variable_groups. If variable_groups = tuple() then it falls back to the classical Newton polytope with all variables in the same part.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Remainder","page":"Constraints","title":"SumOfSquares.Certificate.Remainder","text":"struct Remainder{GCT<:AbstractIdealCertificate} <: AbstractIdealCertificate\n gram_certificate::GCT\nend\n\nThe Remainder certificate ensures the nonnegativity of p(x) for all x such that h_i(x) = 0 by guaranteeing the remainder of p(x) modulo the ideal generated by ⟨h_i⟩ to be nonnegative for all x such that h_i(x) = 0 using the certificate gram_certificate. For instance, if gram_certificate is SumOfSquares.Certificate.Newton, then the certificate Remainder(gram_certificate) will take the remainder before computing the Newton polytope hence might generate a much smaller Newton polytope hence a smaller basis and smaller semidefinite program. However, this then corresponds to a lower degree of the hierarchy which might be insufficient to find a certificate.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.Ideal","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.Ideal","text":"struct Sparsity.Ideal{S <: Sparsity.Pattern, C <: AbstractIdealCertificate} <: SumOfSquares.Certificate.AbstractIdealCertificate\n sparsity::S\n certificate::C\nend\n\nSame certificate as certificate except that the Sum-of-Squares polynomial σ is modelled as a sum of Sum-of-Squares polynomials with smaller bases using the sparsity reduction sparsity.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Symmetry.Ideal","page":"Constraints","title":"SumOfSquares.Certificate.Symmetry.Ideal","text":"struct Symmetry.Ideal{C,GT,AT<:SymbolicWedderburn.Action} <: SumOfSquares.Certificate.AbstractIdealCertificate\n pattern::Symmetry.Pattern{GT,AT}\n certificate::C\nend\n\nSame certificate as certificate except that the Sum-of-Squares polynomial σ is modelled as a sum of Sum-of-Squares polynomials with smaller bases using the Symbolic Wedderburn decomposition of the symmetry pattern specified by pattern.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Preorder certificates:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.Certificate.Putinar\nSumOfSquares.Certificate.Sparsity.Preorder","category":"page"},{"location":"constraints/#SumOfSquares.Certificate.Putinar","page":"Constraints","title":"SumOfSquares.Certificate.Putinar","text":"struct Putinar{\n MC<:AbstractIdealCertificate,\n IC<:AbstractIdealCertificate,\n} <: AbstractPreorderCertificate\n multipliers_certificate::MC\n ideal_certificate::IC\n maxdegree::Int\nend\n\nThe Putinar certificate ensures the nonnegativity of p(x) for all x such that g_i(x) >= 0 and h_i(x) = 0 by exhibiting Sum-of-Squares polynomials σ_i(x) such that p(x) - ∑ σ_i(x) g_i(x) is guaranteed to be nonnegativity for all x such that h_i(x) = 0. The polynomials σ_i(x) are search over cone with a basis of type basis such that the degree of σ_i(x) g_i(x) does not exceed maxdegree.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.Preorder","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.Preorder","text":"struct Sparsity.Preorder{S <: Sparsity.Pattern, C <: SumOfSquares.Certificate.AbstractPreorderCertificate} <: SumOfSquares.Certificate.AbstractPreorderCertificate\n sparsity::S\n certificate::C\nend\n\nSame certificate as C except that the Sum-of-Squares polynomials σ_i are modelled as a sum of Sum-of-Squares polynomials with smaller basis using the sparsity reduction sparsity.\n\n\n\n\n\n","category":"type"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Attributes","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.PolyJuMP.MomentsAttribute\nSumOfSquares.MultivariateMoments.moments(::SumOfSquares.JuMP.ConstraintRef)\nGramMatrix\nSumOfSquares.GramMatrixAttribute\ngram_matrix\ngram_operate\nSumOfSquares.MomentMatrixAttribute\nmoment_matrix\nSumOfSquares.CertificateBasis\ncertificate_basis\ncertificate_monomials\nSumOfSquares.LagrangianMultipliers\nlagrangian_multipliers\nSOSDecomposition\nSOSDecompositionWithDomain\nSumOfSquares.SOSDecompositionAttribute\nsos_decomposition","category":"page"},{"location":"constraints/#PolyJuMP.MomentsAttribute","page":"Constraints","title":"PolyJuMP.MomentsAttribute","text":"MomentsAttribute(N)\nMomentsAttribute()\n\nA constraint attribute for the vector of moments corresponding to the constraint that a polynomial is zero in the full space in result N. If the polynomial is constrained to be zero in an algebraic set, it is the moments for the constraint once it is rewritten into an constraint on the full space. If N is omitted, it is 1 by default.\n\nExamples\n\nConsider the following program:\n\n@variable(model, α)\n@variable(model, β ≤ 1)\n\nusing DynamicPolynomials\n@polyvar x y\ncref = @constraint(model, α * x - β * y == 0, domain = @set x == y)\n\nThe constraint is equivalent to\n\n@constraint(model, (α - β) * y == 0)\n\nfor which the dual is the 1-element vector with the moment of y of value -1. This is the result of moments(cref). However, the dual of cref obtained by dual(cref) is the 2-elements vector with both the moments of x and y of value -1.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#MultivariateMoments.moments-Tuple{ConstraintRef}","page":"Constraints","title":"MultivariateMoments.moments","text":"moments(cref::JuMP.ConstraintRef)\n\nReturn the MomentsAttribute of cref.\n\n\n\n\n\n","category":"method"},{"location":"constraints/#SumOfSquares.GramMatrix","page":"Constraints","title":"SumOfSquares.GramMatrix","text":"struct GramMatrix{T, B, U, MT <: AbstractMatrix{T}} <: AbstractGramMatrix{T, B, U}\n Q::MT\n basis::B\nend\n\nGram matrix x^top Q x where Q is a symmetric matrix indexed by the vector of polynomials of the basis basis.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.GramMatrixAttribute","page":"Constraints","title":"SumOfSquares.GramMatrixAttribute","text":"GramMatrixAttribute(N)\nGramMatrixAttribute()\n\nA constraint attribute for the GramMatrix of a constraint, that is, the positive semidefinite matrix Q indexed by the monomials in the vector X such that X^top Q X is the sum-of-squares certificate of the constraint.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.gram_matrix","page":"Constraints","title":"SumOfSquares.gram_matrix","text":"gram_matrix(cref::JuMP.ConstraintRef)\n\nReturn the GramMatrixAttribute of cref.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.gram_operate","page":"Constraints","title":"SumOfSquares.gram_operate","text":"gram_operate(::typeof(+), p::GramMatrix, q::GramMatrix)\n\nComputes the Gram matrix equal to the sum between p and q. On the opposite, p + q gives a polynomial equal to p + q. The polynomial p + q can also be obtained by polynomial(gram_operate(+, p, q)).\n\n\n\n\n\ngram_operate(/, p::GramMatrix, α)\n\nComputes the Gram matrix equal to p / α. On the opposite, p / α gives a polynomial equal to p / α. The polynomial p / α can also be obtained by polynomial(gram_operate(/, p, α)).\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.MomentMatrixAttribute","page":"Constraints","title":"SumOfSquares.MomentMatrixAttribute","text":"MomentMatrixAttribute(N)\nMomentMatrixAttribute()\n\nA constraint attribute fot the MomentMatrix of a constraint.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#MultivariateMoments.moment_matrix","page":"Constraints","title":"MultivariateMoments.moment_matrix","text":"moment_matrix(cref::JuMP.ConstraintRef)\n\nReturn the MomentMatrixAttribute of cref.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.CertificateBasis","page":"Constraints","title":"SumOfSquares.CertificateBasis","text":"struct CertificateBasis <: MOI.AbstractConstraintAttribute end\n\nA constraint attribute for the basis indexing the GramMatrixAttribute and MomentMatrixAttribute certificates.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.certificate_basis","page":"Constraints","title":"SumOfSquares.certificate_basis","text":"certificate_basis(cref::JuMP.ConstraintRef)\n\nReturn the CertificateBasis of cref.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.certificate_monomials","page":"Constraints","title":"SumOfSquares.certificate_monomials","text":"certificate_monomials(cref::JuMP.ConstraintRef)\n\nReturn the monomials of certificate_basis. If the basis if not MultivariateBases.AbstractMonomialBasis, an error is thrown.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.LagrangianMultipliers","page":"Constraints","title":"SumOfSquares.LagrangianMultipliers","text":"LagrangianMultipliers(N)\nLagrangianMultipliers()\n\nA constraint attribute fot the LagrangianMultipliers associated to the inequalities of the domain of a constraint. There is one multiplier per inequality and no multiplier for equalities as the equalities are handled by reducing the polynomials over the ideal they generate instead of explicitely creating multipliers.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.lagrangian_multipliers","page":"Constraints","title":"SumOfSquares.lagrangian_multipliers","text":"lagrangian_multipliers(cref::JuMP.ConstraintRef)\n\nReturn the LagrangianMultipliers of cref.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.SOSDecomposition","page":"Constraints","title":"SumOfSquares.SOSDecomposition","text":"struct SOSDecomposition{T, PT}\n\nRepresents a Sum-of-Squares decomposition without domain.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.SOSDecompositionWithDomain","page":"Constraints","title":"SumOfSquares.SOSDecompositionWithDomain","text":"struct SOSDecompositionWithDomain{T, PT, S}\n\nRepresents a Sum-of-Squares decomposition on a basic semi-algebraic domain.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.SOSDecompositionAttribute","page":"Constraints","title":"SumOfSquares.SOSDecompositionAttribute","text":"struct SOSDecompositionAttribute\n ranktol::Real\n dec::MultivariateMoments.LowRankLDLTAlgorithm\n result_index::Int\nend\n\nA constraint attribute for the SOSDecomposition of a constraint. By default, it is computed using SOSDecomposition(gram, ranktol, dec) where gram is the value of the GramMatrixAttribute.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.sos_decomposition","page":"Constraints","title":"SumOfSquares.sos_decomposition","text":"sos_decomposition(cref::JuMP.ConstraintRef)\n\nReturn the SOSDecompositionAttribute of cref.\n\n\n\n\n\nsos_decomposition(cref::JuMP.ConstraintRef, K<:AbstractBasicSemialgebraicSet)\n\nReturn representation in the quadraic module associated with K.\n\n\n\n\n\n","category":"function"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Bridges are automatically added using the following utilities:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.PolyJuMP.bridgeable\nSumOfSquares.PolyJuMP.bridges","category":"page"},{"location":"constraints/#PolyJuMP.bridgeable","page":"Constraints","title":"PolyJuMP.bridgeable","text":"bridgeable(c::JuMP.AbstractConstraint, S::Type{<:MOI.AbstractSet})\n\nWrap the constraint c in JuMP.BridgeableConstraints that may be needed to bridge variables constrained in S on creation.\n\nbridgeable(c::JuMP.AbstractConstraint, F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet})\n\nWrap the constraint c in JuMP.BridgeableConstraints that may be needed to bridge F-in-S constraints.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#PolyJuMP.bridges","page":"Constraints","title":"PolyJuMP.bridges","text":"bridges(F::Type{<:MOI.AbstractFunction}, S::Type{<:MOI.AbstractSet})\n\nReturn a list of bridges that may be needed to bridge F-in-S constraints but not the bridges that may be needed by constraints added by the bridges.\n\n\n\n\n\nbridges(S::Type{<:MOI.AbstractSet})\n\nReturn a list of bridges that may be needed to bridge variables constrained in S on creation but not the bridges that may be needed by constraints added by the bridges.\n\n\n\n\n\n","category":"function"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Chordal extension:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.neighbors\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.fill_in\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.is_clique\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.LabelledGraph\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_node!\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_edge!\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_clique!\nSumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.completion","category":"page"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.neighbors","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.neighbors","text":"neighbors(G::Graph, node::Int}\n\nReturn neighbors of node in G.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.fill_in","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.fill_in","text":"fill_in(G::Graph{T}, i::T}\n\nReturn number of edges that need to be added to make the neighbors of i a clique.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.is_clique","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.is_clique","text":"is_clique(G::Graph{T}, x::Vector{T})\n\nReturn a Bool indication whether x is a clique in G.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.LabelledGraph","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.LabelledGraph","text":"struct LabelledGraph{T}\n n2int::Dict{T,Int}\n int2n::Vector{T}\n graph::Graph\nend\n\nType to represend a graph with nodes of type T.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_node!","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_node!","text":"add_node!(G::LabelledGraph{T}, i::T) where T\n\nAdd the node i to graph G. If i is already a node of G, only return the reference.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_edge!","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_edge!","text":"add_edge!(G::LabelledGraph{T}, i::T, j::T) where T\n\nAdd the unweighted edge (i, j) to graph G. Duplicate edges are not taken into account.\n\n\n\n\n\nadd_edge!(G::LabelledGraph{T}, e::Tuple{T,T}) where T\n\nAdd the unweighted edge e to graph G. Duplicate edges are not taken into account.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_clique!","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.add_clique!","text":"add_clique!(G::LabelledGraph{T}, x::Vector{T}) where T\n\nAdd all elements of x as nodes to G and add edges such that x is fully connected in G.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.completion","page":"Constraints","title":"SumOfSquares.Certificate.Sparsity.ChordalExtensionGraph.completion","text":"completion(G::Graph, comp::ChordalCompletion)\n\nReturn a chordal extension of G and the corresponding maximal cliques.\n\nThe algoritm is Algorithm 3 in [BA10] with the GreedyFillIn heuristic of Table I.\n\n[BA10] Bodlaender, Hans L., and Arie MCA Koster. Treewidth computations I. Upper bounds. Information and Computation 208, no. 3 (2010): 259-275. Utrecht University, Utrecht, The Netherlands www.cs.uu.nl\n\n\n\n\n\ncompletion(G::Graph, comp::ChordalCompletion)\n\nReturn a cluster completion of G and the corresponding maximal cliques.\n\n\n\n\n\n","category":"function"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"Bridges for polynomial optimization","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"PolyJuMP.ScalarPolynomialFunction\nPolyJuMP.Bridges.Objective.ToPolynomialBridge\nPolyJuMP.Bridges.Constraint.ToPolynomialBridge","category":"page"},{"location":"constraints/#PolyJuMP.ScalarPolynomialFunction","page":"Constraints","title":"PolyJuMP.ScalarPolynomialFunction","text":"struct ScalarPolynomialFunction{T,P<:MP.AbstractPolynomial{T}} <: MOI.AbstractScalarFunction\n polynomial::P\n variables::Vector{MOI.VariableIndex}\nend\n\nDefines the polynomial function of the variables variables where the variable variables(p)[i] corresponds to variables[i].\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.Bridges.Objective.ToPolynomialBridge","page":"Constraints","title":"PolyJuMP.Bridges.Objective.ToPolynomialBridge","text":"ToPolynomialBridge{T}\n\nToPolynomialBridge implements the following reformulations:\n\nmin f(x) into minp(x)\nmax f(x) into maxp(x)\n\nwhere f(x) is a scalar function and p(x) is a polynomial.\n\nSource node\n\nToPolynomialBridge supports:\n\nMOI.ObjectiveFunction{F} where F is a MOI.AbstractScalarFunction for which convert(::Type{PolyJuMP.ScalarPolynomialFunction}, ::Type{F}). That is for instance the case for MOI.VariableIndex, MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction.\n\nTarget nodes\n\nToPolynomialBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{PolyJuMP.ScalarPolynomialFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.Bridges.Constraint.ToPolynomialBridge","page":"Constraints","title":"PolyJuMP.Bridges.Constraint.ToPolynomialBridge","text":"ToPolynomialBridge{T,S} <: Bridges.Constraint.AbstractBridge\n\nToPolynomialBridge implements the following reformulations:\n\nf(x) in S into p(x) in S where f(x) is a scalar function and p(x) is a polynomial.\n\nSource node\n\nToPolynomialBridge supports:\n\nF in S where F is a MOI.AbstractScalarFunction for which\n\nconvert(::Type{PolyJuMP.ScalarPolynomialFunction}, ::Type{F}). That is for instance the case for MOI.VariableIndex, MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction.\n\nTarget nodes\n\nToPolynomialBridge creates:\n\nPolyJuMP.ScalarPolynomialFunction{T} in S\n\n\n\n\n\n","category":"type"},{"location":"constraints/#SAGE-extension","page":"Constraints","title":"SAGE extension","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"To use the SAGE cone in place of the Sum-of-Squares cone for an inequality constraints between polynomials, use the following:","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"import PolyJuMP\nPolyJuMP.setpolymodule!(model, PolyJuMP.SAGE)","category":"page"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.PolyJuMP.SAGE.Polynomials\nSumOfSquares.PolyJuMP.SAGE.Decomposition\nSumOfSquares.PolyJuMP.SAGE.Signomials\nSumOfSquares.PolyJuMP.SAGE.DecompositionAttribute\nSumOfSquares.PolyJuMP.SAGE.SignomialsBridge\nSumOfSquares.PolyJuMP.SAGE.AGEBridge","category":"page"},{"location":"constraints/#PolyJuMP.SAGE.Polynomials","page":"Constraints","title":"PolyJuMP.SAGE.Polynomials","text":"struct Polynomials{M<:Union{Nothing,Int,MP.AbstractMonomial}} <: PolyJuMP.PolynomialSet\n\nSums of AM/GM Exponential for polynomials.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.SAGE.Decomposition","page":"Constraints","title":"PolyJuMP.SAGE.Decomposition","text":"struct Decomposition{T, PT}\n\nRepresents a SAGE decomposition.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.SAGE.Signomials","page":"Constraints","title":"PolyJuMP.SAGE.Signomials","text":"struct Signomials{M<:Union{Nothing,Int,MP.AbstractMonomial}} <: PolyJuMP.PolynomialSet\n\nSums of AM/GM Exponential for signomials.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.SAGE.DecompositionAttribute","page":"Constraints","title":"PolyJuMP.SAGE.DecompositionAttribute","text":"struct DecompositionAttribute{T} <: MOI.AbstractConstraintAttribute\n tol::T\nend\n\nA constraint attribute for the Decomposition of a constraint.\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.SAGE.SignomialsBridge","page":"Constraints","title":"PolyJuMP.SAGE.SignomialsBridge","text":"SignomialsBridge{T,S,P,F} <: MOI.Bridges.Constraint.AbstractBridge\n\nWe use the Signomials Representative SR equation of [MCW21].\n\n[MCW20] Riley Murray, Venkat Chandrasekaran, Adam Wierman \"Newton Polytopes and Relative Entropy Optimization\" https://arxiv.org/abs/1810.01614 [MCW21] Murray, Riley, Venkat Chandrasekaran, and Adam Wierman. \"Signomials and polynomial optimization via relative entropy and partial dualization.\" Mathematical Programming Computation 13 (2021): 257-295. https://arxiv.org/pdf/1907.00814.pdf\n\n\n\n\n\n","category":"type"},{"location":"constraints/#PolyJuMP.SAGE.AGEBridge","page":"Constraints","title":"PolyJuMP.SAGE.AGEBridge","text":"AGEBridge{T,F,G,H} <: MOI.Bridges.Constraint.AbstractBridge\n\nThe nonnegativity of x ≥ 0 in\n\n∑ ci x^αi ≥ -c0 x^α0\n\ncan be reformulated as\n\n∑ ci exp(αi'y) ≥ -β exp(α0'y)\n\nIn any case, it is shown to be equivalent to\n\n∃ ν ≥ 0 s.t. D(ν, exp(1)*c) ≤ β, ∑ νi αi = α0 ∑ νi [CP16, (3)]\n\nwhere N(ν, λ) = ∑ νj log(νj/λj) is the relative entropy function. The constant exp(1) can also be moved out of D into\n\n∃ ν ≥ 0 s.t. D(ν, c) - ∑ νi ≤ β, ∑ νi αi = α0 ∑ νi [MCW21, (2)]\n\nThe relative entropy cone in MOI is (u, v, w) such that D(w, v) ≥ u. Therefore, we can either encode (β, exp(1)*c, ν) [CP16, (3)] or (β + ∑ νi, c, ν) [MCW21, (2)]. In this bridge, we use the second formulation.\n\nnote: Note\nA direct application of the Arithmetic-Geometric mean inequality gives∃ ν ≥ 0 s.t. D(ν, exp(1)*c) ≤ -log(-β), ∑ νi αi = α0, ∑ νi = 1 [CP16, (4)]which is not jointly convex in (ν, c, β). The key to get the convex formulation [CP16, (3)] or [MCW21, (2)] instead is to use the convex conjugacy between the exponential and the negative entropy functions [CP16, (iv)].\n\n[CP16] Chandrasekaran, Venkat, and Parikshit Shah. \"Relative entropy relaxations for signomial optimization.\" SIAM Journal on Optimization 26.2 (2016): 1147-1173. [MCW21] Murray, Riley, Venkat Chandrasekaran, and Adam Wierman. \"Signomials and polynomial optimization via relative entropy and partial dualization.\" Mathematical Programming Computation 13 (2021): 257-295. https://arxiv.org/pdf/1907.00814.pdf\n\n\n\n\n\n","category":"type"},{"location":"constraints/#Internal-functions","page":"Constraints","title":"Internal functions","text":"","category":"section"},{"location":"constraints/","page":"Constraints","title":"Constraints","text":"SumOfSquares.Certificate.Symmetry.orthogonal_transformation_to\nSumOfSquares.Certificate.Symmetry._reorder!\nSumOfSquares.Certificate.Symmetry._rotate_complex\nPolyJuMP.QCQP._subs_ensure_moi_order","category":"page"},{"location":"constraints/#SumOfSquares.Certificate.Symmetry.orthogonal_transformation_to","page":"Constraints","title":"SumOfSquares.Certificate.Symmetry.orthogonal_transformation_to","text":"orthogonal_transformation_to(A, B)\n\nReturn an orthogonal transformation U such that A = U' * B * U\n\nGiven Schur decompositions A = Z_A * S_A * Z_A' B = Z_B * S_B * Z_B' Since P' * S_A * P = D' * S_B * D, we have A = Z_A * P * Z_B' * B * Z_B * P' * Z_A'\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Symmetry._reorder!","page":"Constraints","title":"SumOfSquares.Certificate.Symmetry._reorder!","text":"_reorder!(F::LinearAlgebra.Schur{T}) where {T}\n\nGiven a Schur decomposition of a, reorder it so that its eigenvalues are in in increasing order.\n\nNote that if T<:Real, F.Schur is quasi upper triangular. By (quasi), we mean that there may be nonzero entries in S[i+1,i] representing complex conjugates. In that case, the complex conjugate are permuted together. If T<:Complex, then S is triangular.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#SumOfSquares.Certificate.Symmetry._rotate_complex","page":"Constraints","title":"SumOfSquares.Certificate.Symmetry._rotate_complex","text":"_rotate_complex(A::AbstractMatrix{T}, B::AbstractMatrix{T}; tol = Base.rtoldefault(real(T))) where {T}\n\nGiven (quasi) upper triangular matrix A and B that have the eigenvalues in the same order except the complex pairs which may need to be (signed) permuted, returns an othogonal matrix P such that P' * A * P and B have matching low triangular part. The upper triangular part will be dealt with by _sign_diag.\n\nBy (quasi), we mean that if S is a Matrix{<:Real}, then there may be nonzero entries in S[i+1,i] representing complex conjugates. If S is a Matrix{<:Complex}, then S is upper triangular so there is nothing to do.\n\n\n\n\n\n","category":"function"},{"location":"constraints/#PolyJuMP.QCQP._subs_ensure_moi_order","page":"Constraints","title":"PolyJuMP.QCQP._subs_ensure_moi_order","text":"_subs_ensure_moi_order(p::PolyJuMP.ScalarPolynomialFunction, old, new)\n\nSubstitutes old MP.variables(p.polynomial) with new vars, while re-sorting the MOI p.variables to get them in the correct order after substitution.\n\n\n\n\n\n","category":"function"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"EditURL = \"../../tutorials/Extension/certificate.jl\"","category":"page"},{"location":"generated/Extension/certificate/#Certificate","page":"Certificate","title":"Certificate","text":"","category":"section"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Extension/certificate/#Introduction","page":"Certificate","title":"Introduction","text":"","category":"section"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"Consider the polynomial optimization problem (a variation from (Lasserre, 2009; Example 2.2)) of minimizing the polynomial x^3 - x^2 + 2xy - y^2 + y^3 over the polyhedron defined by the inequalities x ge 0 y ge 0 and x + y geq 1.","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"using DynamicPolynomials\n@polyvar x y\np = x^3 - x^2 + 2x*y - y^2 + y^3 + x^3 * y\nusing SumOfSquares\nS = @set x >= 0 && y >= 0 && x^2 + y^2 >= 2","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices. Note that SumOfSquares generates a standard form SDP (i.e., SDP variables and equality constraints) while SCS expects a geometric form SDP (i.e., free variables and symmetric matrices depending affinely on these variables constrained to belong to the PSD cone). JuMP will transform the standard from to the geometric form will create the PSD variables as free variables and then constrain then to be PSD. While this will work, since the dual of a standard from is in in geometric form, dualizing the problem will generate a smaller SDP. We use therefore Dualization.dual_optimizer so that SCS solves the dual problem.","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"import SCS\nusing Dualization\nsolver = dual_optimizer(SCS.Optimizer)","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following program searches for the largest lower bound.","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"model = SOSModel(solver)\n@variable(model, α)\n@objective(model, Max, α)\n@constraint(model, c, p >= α, domain = S)\noptimize!(model)","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"We can see that the problem is infeasible, meaning that no lower bound was found.","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"solution_summary(model)","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"We now define the Schmüdgen's certificate:","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"import MultivariateBases as MB\nconst SOS = SumOfSquares\nconst SOSC = SOS.Certificate\nstruct Schmüdgen{IC <: SOSC.AbstractIdealCertificate, CT <: SOS.SOSLikeCone, BT <: SOS.AbstractPolynomialBasis} <: SOSC.AbstractPreorderCertificate\n ideal_certificate::IC\n cone::CT\n basis::Type{BT}\n maxdegree::Int\nend\n\nSOSC.cone(certificate::Schmüdgen) = certificate.cone\n\nfunction SOSC.preprocessed_domain(::Schmüdgen, domain::BasicSemialgebraicSet, p)\n return SOSC.with_variables(domain, p)\nend\n\nfunction SOSC.preorder_indices(::Schmüdgen, domain::SOSC.WithVariables)\n n = length(domain.inner.p)\n if n >= Sys.WORD_SIZE\n error(\"There are $(2^n - 1) products in Schmüdgen's certificate, they cannot even be indexed with `$Int`.\")\n end\n return map(SOSC.PreorderIndex, 1:(2^n-1))\nend\n\nfunction SOSC.multiplier_basis(certificate::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables)\n q = SOSC.generator(certificate, index, domain)\n return SOSC.maxdegree_gram_basis(certificate.basis, variables(domain), SOSC.multiplier_maxdegree(certificate.maxdegree, q))\nend\nfunction SOSC.multiplier_basis_type(::Type{Schmüdgen{IC, CT, BT}}) where {IC, CT, BT}\n return BT\nend\n\nfunction SOSC.generator(::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables)\n I = [i for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))]\n return prod([domain.inner.p[i] for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))])\nend\n\nSOSC.ideal_certificate(certificate::Schmüdgen) = certificate.ideal_certificate\nSOSC.ideal_certificate(::Type{<:Schmüdgen{IC}}) where {IC} = IC\n\nSOS.matrix_cone_type(::Type{<:Schmüdgen{IC, CT}}) where {IC, CT} = SOS.matrix_cone_type(CT)","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"Let's try again with our the Schmüdgen certificate:","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"model = SOSModel(solver)\n@variable(model, α)\n@objective(model, Max, α)\nideal_certificate = SOSC.Newton(SOSCone(), MB.MonomialBasis, tuple())\ncertificate = Schmüdgen(ideal_certificate, SOSCone(), MB.MonomialBasis, maxdegree(p))\n@constraint(model, c, p >= α, domain = S, certificate = certificate)\noptimize!(model)\nsolution_summary(model)","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"","category":"page"},{"location":"generated/Extension/certificate/","page":"Certificate","title":"Certificate","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"EditURL = \"../../tutorials/Getting started/motzkin.jl\"","category":"page"},{"location":"generated/Getting started/motzkin/#Motzkin","page":"Motzkin","title":"Motzkin","text":"","category":"section"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"(Image: ) (Image: ) Adapted from: (3.6) and (3.19) of [BPT12]","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"The first explicit example of nonnegative polynomial that is not a sum of squares was found by Motzkin in 1967. By the Arithmetic-geometric mean, $ \\frac{x^4y^2 + x^2y^4 + 1}{3} \\ge \\sqrt[3]{x^4y^2 \\cdot x^2y^4 \\cdot 1} = x^2y^2 $ hence $ x^4y^2 + x^2y^4 + 1 - 3x^2y^2 \\ge 0. $ The code belows construct the Motzkin polynomial using DynamicPolynomials.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"using DynamicPolynomials\n@polyvar x y\nmotzkin = x^4*y^2 + x^2*y^4 + 1 - 3x^2*y^2","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"The Motzkin polynomial is nonnegative but is not a sum of squares as we can verify numerically as follows. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"using SumOfSquares\nimport CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = SOSModel(solver)\n@constraint(model, motzkin >= 0) # We constraint `motzkin` to be a sum of squares\n\noptimize!(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"We see that the problem is detected as infeasible...","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"termination_status(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"... and that the dual solution is a certificate of the infeasibility of the problem.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"dual_status(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"Even if the Motzkin polynomial is not a sum of squares, it can still be certified to be nonnegative using sums of squares. Indeed a polynomial is certified to be nonnegative if it is equal to a fraction of sums of squares. The Motzkin polynomial is equal to a fraction of sums of squares whose denominator is x^2 + y^2. This can be verified numerically as follows:","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"model = SOSModel(solver)\n@constraint(model, (x^2 + y^2) * motzkin >= 0) # We constraint the `(x^2 + y^2) * motzkin` to be a sum of squares\n\noptimize!(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"Now the problem is declared feasible by the solver...","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"termination_status(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"... and the primal solution is a feasible point, hence it is a certificate of nonnegativity of the Motzkin polynomial.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"primal_status(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"One may consider ourself lucky to have had the intuition that x^2 + y^2 would work as denominator. In fact, the search for the denominator can be carried out in parallel to the search of the numerator. In the example below, we search for a denominator with monomials of degrees from 0 to 2. If none is found, we can increase the maximum degree 2 to 4, 6, 8, ... This gives a hierarchy of programs to try in order to certify the nonnegativity of a polynomial by identifying it with a fraction of sum of squares polynomials. In the case of the Motzkin polynomial we now that degree 2 is enough since x^2 + y^2 works.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"model = SOSModel(solver)\nX = monomials([x, y], 0:2)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"We create a quadratic polynomial that is not necessarily a sum of squares since this is implied by the next constraint: deno >= 1.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"@variable(model, deno, Poly(X))","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"We want the denominator polynomial to be strictly positive, this prevents the trivial solution deno = 0 for instance.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"@constraint(model, deno >= 1)\n@constraint(model, deno * motzkin >= 0)\noptimize!(model)\n\ntermination_status(model)\n\nprimal_status(model)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"We can check the denominator found by the program using JuMP.value","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"value(deno)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"Because a picture is worth a thousand words let's plot the beast. We can easily extend Plots by adding a recipe to plot bivariate polynomials.","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"using RecipesBase\n@recipe function f(x::AbstractVector, y::AbstractVector, p::Polynomial)\n x, y, (x, y) -> p(variables(p) => [x, y])\nend\nimport Plots\nPlots.plot(\n range(-2, stop=2, length=100),\n range(-2, stop=2, length=100),\n motzkin,\n st = [:surface],\n seriescolor=:heat,\n colorbar=:none,\n clims = (-10, 80)\n)","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"","category":"page"},{"location":"generated/Getting started/motzkin/","page":"Motzkin","title":"Motzkin","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"EditURL = \"../../tutorials/Getting started/univariate.jl\"","category":"page"},{"location":"generated/Getting started/univariate/#Minimization-of-a-univariate-polynomial","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"","category":"section"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"using DynamicPolynomials\nusing SumOfSquares\nimport CSDP","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Consider the problem of finding both the minimum value of p = x^4 - 4x^3 - 2x^2 + 12x + 3 as well as its minimizers.","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"We can use SumOfSquares.jl to find such these values as follows. We first define the polynomial using DynamicPolynomials.","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"@polyvar x\np = x^4 - 4x^3 - 2x^2 + 12x + 3","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Secondly, we create a Sum-of-Squares program searching for the maximal lower bound σ of the polynomial.","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"model = SOSModel(CSDP.Optimizer)\n@variable(model, σ)\n@constraint(model, cref, p >= σ)\n@objective(model, Max, σ)","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Thirdly, solve the program and find σ = -6 as lower bound:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"optimize!(model)\nsolution_summary(model)","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"We can look at the certificate that σ = -6 is a lower bound:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"sos_dec = sos_decomposition(cref, 1e-4)","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Indeed, p + 6 = (x^2 - 2x - 3)^2 so p ≥ -6.","category":"page"},{"location":"generated/Getting started/univariate/#Extraction-of-minimizers","page":"Minimization of a univariate polynomial","title":"Extraction of minimizers","text":"","category":"section"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"We can now find the minimizers from the moment matrix:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"ν = moment_matrix(cref)\nν.Q","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"This matrix is the convex combination of the moment matrices corresponding to two atomic measures at -1 and 3 which allows us to conclude that -1 and 3 are global minimizers.","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"η = atomic_measure(ν, 1e-4)\nminimizers = [η.atoms[1].center; η.atoms[2].center]","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Below are more details on what we mean by convex combination. The moment matrix of the atomic measure at the first minimizer is:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"η1 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[1])), ν.basis.monomials)\nη1.Q","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"The moment matrix of the atomic measure at the second minimizer is:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"η2 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[2])), ν.basis.monomials)\nη2.Q","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"And the moment matrix is the convex combination of both:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Q12 = η1.Q * η.atoms[1].weight + η2.Q * η.atoms[2].weight","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Another way to see this (by linearity of the expectation) is that ν is the moment matrix of the convex combination of the two atomic measures.","category":"page"},{"location":"generated/Getting started/univariate/#Changing-the-polynomial-basis","page":"Minimization of a univariate polynomial","title":"Changing the polynomial basis","text":"","category":"section"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"The monomial basis used by default can leave a problem quite ill-conditioned for the solver. Let's try to use another basis instead:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"model = SOSModel(CSDP.Optimizer)\n@variable(model, σ)\n@constraint(model, cheby_cref, p >= σ, basis = ChebyshevBasisFirstKind)\n@objective(model, Max, σ)\noptimize!(model)\nsolution_summary(model)","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"Although the gram matrix in the monomial basis:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"g = gram_matrix(cref)\n@show g.basis\ng.Q","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"looks different from the gram matrix in the Chebyshev basis:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"cheby_g = gram_matrix(cheby_cref)\n@show cheby_g.basis\ncheby_g.Q","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"they both yields the same Sum-of-Squares decomposition:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"cheby_sos_dec = sos_decomposition(cheby_cref, 1e-4)","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"The gram matrix in the Chebyshev basis can be understood as follows. To express the polynomial -x^2 + 2x + 3 in the Chebyshev basis, we start by substituting x into cos(theta) to obtain -cos(theta)^2 + 2cos(theta) + 3. We now express it as a combination of cos(ntheta) for n = 0 1 2: -(2cos(theta) - 1) 2 + 2 cos(theta) + 52 Therefore, the coefficients in the Chebyshev basis is:","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"cheby_coefs = [5/2, 2, -1/2]","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"We can indeed observe that we obtain the same matrix as cheby_g.Q","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"cheby_coefs * cheby_coefs'","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"","category":"page"},{"location":"generated/Getting started/univariate/","page":"Minimization of a univariate polynomial","title":"Minimization of a univariate polynomial","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"EditURL = \"../../tutorials/Other Applications/bounds_in_probability.jl\"","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/#Bounds-in-Probability","page":"Bounds in Probability","title":"Bounds in Probability","text":"","category":"section"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"(Image: ) (Image: ) Adapted from: SOSTOOLS' SOSDEMO8 (See Section 4.8 of SOSTOOLS User's Manual)","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The probability adds up to one.","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"μ0 = 1","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The mean is one.","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"μ1 = 1","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The standard deviation is 1/2.","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"σ = 1/2","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The second moment E(x^2) is:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"μ2 = σ^2 + μ1^2","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"We define the moments as follows:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"using DynamicPolynomials\n@polyvar x\nmonos = [1, x, x^2]\nusing SumOfSquares\nμ = measure([μ0, μ1, μ2], monos)","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"using CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = SOSModel(solver);\nnothing #hide","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"We create a polynomial with the monomials in monos and JuMP decision variables as coefficients as follows:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"@variable(model, poly, Poly(monos))","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"Nonnegative on the support:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"K = @set 0 <= x && x <= 5\ncon_ref = @constraint(model, poly >= 0, domain = K)","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"Greater than one on the event:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"@constraint(model, poly >= 1, domain = (@set 4 <= x && x <= 5))","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The bound (we use LinearAlgebra for the ⋅ syntax for the scalar product):","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"using LinearAlgebra\n@objective(model, Min, poly ⋅ μ)","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"We verify that we found a feasible solution:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"optimize!(model)\nprimal_status(model)","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The objective value is 1/37:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"objective_value(model)","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"The solution is (12x-11)^2 / 37^2:","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"value(poly) * 37^2","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"","category":"page"},{"location":"generated/Other Applications/bounds_in_probability/","page":"Bounds in Probability","title":"Bounds in Probability","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"EditURL = \"../../tutorials/Extension/hypercube.jl\"","category":"page"},{"location":"generated/Extension/hypercube/#Hypercube","page":"Hypercube","title":"Hypercube","text":"","category":"section"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"Given a Sum-of-Squares constraint on an algebraic set:","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"g_1(x) = ldots g_m(x) = 0 Rightarrow p(x) ge 0","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"We can either use the certificate:","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"p(x) = s(x) + lambda_1(x) g_1(x) + cdots + lambda_m(x) g_m(x) s_0(x) text is SOS","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"or","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"p(x) equiv s(x) pmodla g_1(x) ldots g_m(x) ra s_0(x) text is SOS","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"the second one leads to a simpler SDP but needs to compute a Gr\\\"obner basis:","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"SemialgebraicSets implements Buchberger's algorithm.\nThe @set macro recognizes variable fix, e.g., x = 1 and provides shortcut.\nIf you know a \\alert{better} way to take modulo, better create your \\alert{own} type of algebraic set!","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"We illustrate this in this example.","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"using DynamicPolynomials\n@polyvar x[1:3]\np = sum(x)^2\nusing SumOfSquares\nS = algebraicset([xi^2 - 1 for xi in x])","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"We will now search for the minimum of x over S using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"import CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\n\nfunction min_algebraic(S)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = S)\n optimize!(model)\n @show termination_status(model)\n @show objective_value(model)\nend\n\nmin_algebraic(S)","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"Note that the minimum is in fact 1. Indeed, since each variables is odd (it is either -1 or 1) and there is an odd number of variables, their sum is odd. Therefore it cannot be zero!","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"We can see that the Gröbner basis of S was computed","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"@show S.I.gröbner_basis\nS.I.algo","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"The Gröbner basis is simple to compute in this case as the vector of xi^2 - 1 is already a Gröbner basis. However, we still need to divide polynomials by the Gröbner basis which can be simplified in this case.","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"const MP = MultivariatePolynomials\nconst SS = SemialgebraicSets\nstruct HypercubeIdeal{V} <: SS.AbstractPolynomialIdeal\n variables::Vector{V}\nend\nstruct HypercubeSet{V} <: SS.AbstractAlgebraicSet\n ideal::HypercubeIdeal{V}\nend\nMP.variables(set::HypercubeSet) = MP.variables(set.ideal)\nMP.variables(ideal::HypercubeIdeal) = ideal.variables\nBase.similar(set::HypercubeSet, ::Type) = set\nSS.ideal(set::HypercubeSet) = set.ideal\nfunction Base.rem(p, set::HypercubeIdeal)\n return MP.polynomial(map(MP.terms(p)) do term\n mono = MP.monomial(term)\n new_mono = one(mono)\n for (var, exp) in powers(mono)\n if var in set.variables\n exp = rem(exp, 2)\n end\n new_mono *= var^exp\n end\n MP.coefficient(term) * new_mono\n end)\nend\n\nH = HypercubeSet(HypercubeIdeal(x))\n\nmin_algebraic(H)","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"Let's now try to find the correct lower bound:","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"function min_algebraic_rational(S, d)\n model = SOSModel(solver)\n @variable(model, q, SOSPoly(MP.monomials(x, 0:d)))\n deno = q + 1\n @constraint(model, c, deno * p >= deno, domain = S)\n optimize!(model)\n @show termination_status(model)\nend","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"With d = 0, it's the same as previously","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"min_algebraic_rational(H, 0)","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"But with d = 1, we can find the correct lower bound","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"min_algebraic_rational(H, 1)","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"","category":"page"},{"location":"generated/Extension/hypercube/","page":"Hypercube","title":"Hypercube","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"EditURL = \"../../tutorials/Polynomial Optimization/qp.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/qp/#Nonconvex-QP","page":"Nonconvex QP","title":"Nonconvex QP","text":"","category":"section"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"(Image: ) (Image: ) Adapted from: of (Floudas et al., 1999; Section 2.2), (Lasserre, 2009; Table 5.1)","category":"page"},{"location":"generated/Polynomial Optimization/qp/#Introduction","page":"Nonconvex QP","title":"Introduction","text":"","category":"section"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"Consider the nonconvex Quadratic Program (QP) from (Floudas et al., 1999; Section 2.2) that minimizes the concave function c^top x - x^top Qx 2 over the polyhedron obtained by intersecting the hypercube 0 1^5 with the halfspace 10x_1 + 12x_2 + 11x_3 + 7x_4 + 4x_5 le 40.","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"using LinearAlgebra\nc = [42, 44, 45, 47, 47.5]\nQ = 100I\n\nusing DynamicPolynomials\n@polyvar x[1:5]\np = c'x - x' * Q * x / 2\nusing SumOfSquares\nK = @set x[1] >= 0 && x[1] <= 1 &&\n x[2] >= 0 && x[2] <= 1 &&\n x[3] >= 0 && x[3] <= 1 &&\n x[4] >= 0 && x[4] <= 1 &&\n x[5] >= 0 && x[5] <= 1 &&\n 10x[1] + 12x[2] + 11x[3] + 7x[4] + 4x[5] <= 40","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"import Clarabel\nsolver = Clarabel.Optimizer","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"function solve(d)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = K, maxdegree = d)\n optimize!(model)\n println(solution_summary(model))\n return model\nend","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"The first level of the hierarchy does not give any lower bound:","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"model2 = solve(2)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"Indeed, as the constraints have degree 1 and their multipliers are SOS so they have an even degree, with maxdegree 2 we can only use degree 0 multipliers hence constants. The terms of maximal degree in resulting sum will therefore only be in -x' * Q * x/2 hence it is not SOS whatever is the value of the multipliers. Let's try with maxdegree 3 so that the multipliers can be quadratic. This second level is now feasible and gives a lower bound of -22.","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"model3 = solve(3)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"","category":"page"},{"location":"generated/Polynomial Optimization/qp/","page":"Nonconvex QP","title":"Nonconvex QP","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"EditURL = \"../../tutorials/Sparsity/term_sparsity.jl\"","category":"page"},{"location":"generated/Sparsity/term_sparsity/#Term-sparsity","page":"Term sparsity","title":"Term sparsity","text":"","category":"section"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"(Image: ) (Image: ) Adapted from: Example 3.5 of [WML20b]","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"[WML20a] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. TSSOS: A Moment-SOS hierarchy that exploits term sparsity. arXiv preprint arXiv:1912.08899 (2020).","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"[WML20b] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension. arXiv preprint arXiv:2003.03210 (2020).","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"using DynamicPolynomials\n@polyvar x[1:3]","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"We would like to find the minimum value of the polynomial","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"poly = x[1]^2 - 2x[1]*x[2] + 3x[2]^2 - 2x[1]^2*x[2] + 2x[1]^2*x[2]^2 - 2x[2]*x[3] + 6x[3]^2 + 18x[2]^2*x[3] - 54x[2]*x[3]^2 + 142x[2]^2*x[3]^2","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"The minimum value of the polynomial can be found to be zero.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"import CSDP\nsolver = CSDP.Optimizer\nusing SumOfSquares\nfunction sos_min(sparsity)\n model = Model(solver)\n @variable(model, t)\n @objective(model, Max, t)\n con_ref = @constraint(model, poly - t in SOSCone(), sparsity = sparsity)\n optimize!(model)\n return value(t), moment_matrix(con_ref)\nend\n\nbound, ν = sos_min(Sparsity.NoPattern())\nbound","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"We find the corresponding minimizer (0, 0, 0) by matching the moments of the moment matrix with a dirac measure centered at this minimizer.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"atomic_measure(ν, 1e-6)","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"We can see below that the basis contained 6 monomials hence we needed to use 6x6 PSD matrix variables.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"ν.basis","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"Using the monomial/term sparsity method of [WML20a] based on cluster completion, we find the same bound.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"bound, ν = sos_min(Sparsity.Monomial())\nbound","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"Which is not suprising as no sparsity reduction could be performed.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"[sub.basis for sub in ν.blocks]","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"Using the monomial/term sparsity method of [WML20b] based on chordal completion, the lower bound is smaller than 0.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"bound, ν = sos_min(Sparsity.Monomial(ChordalCompletion()))\nbound","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"However, this bound was obtained with an SDP with 4 matrices of size 3x3.","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"[sub.basis for sub in ν.blocks]","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"","category":"page"},{"location":"generated/Sparsity/term_sparsity/","page":"Term sparsity","title":"Term sparsity","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Noncommutative and Hermitian/sums_of_hermitian_squares/","page":"Sums of Hermitian squares","title":"Sums of Hermitian squares","text":"EditURL = \"../../tutorials/Noncommutative and Hermitian/sums_of_hermitian_squares.jl\"","category":"page"},{"location":"generated/Noncommutative and Hermitian/sums_of_hermitian_squares/#Sums-of-Hermitian-squares","page":"Sums of Hermitian squares","title":"Sums of Hermitian squares","text":"","category":"section"},{"location":"generated/Noncommutative and Hermitian/sums_of_hermitian_squares/","page":"Sums of Hermitian squares","title":"Sums of Hermitian squares","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Noncommutative and Hermitian/sums_of_hermitian_squares/","page":"Sums of Hermitian squares","title":"Sums of Hermitian squares","text":"using SumOfSquares\n\nusing DynamicPolynomials\n@ncpolyvar x y\np = (x + im * y) * (x - im * y)\n\nimport CSDP\nmodel = Model(CSDP.Optimizer)\ncone = NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}()\ncon_ref = @constraint(model, p in cone)\noptimize!(model)\nsos_decomposition(con_ref, 1e-6)","category":"page"},{"location":"generated/Noncommutative and Hermitian/sums_of_hermitian_squares/","page":"Sums of Hermitian squares","title":"Sums of Hermitian squares","text":"","category":"page"},{"location":"generated/Noncommutative and Hermitian/sums_of_hermitian_squares/","page":"Sums of Hermitian squares","title":"Sums of Hermitian squares","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"EditURL = \"../../tutorials/Getting started/dualization.jl\"","category":"page"},{"location":"generated/Getting started/dualization/#On-the-importance-of-Dualization","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"(Image: ) (Image: )","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"using DynamicPolynomials\nusing SumOfSquares","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"Sum-of-Squares programs are usually solved by SemiDefinite Programming solvers (SDPs). These programs can be represented into two different formats: Either the standard conic form, also known as kernel form:","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"beginaligned\n minlimits_Q in mathbbS_n langle C Q rangle\n textsubject to langle A_i Q rangle = b_i quad i=12ldotsm\n Q succeq 0\nendaligned","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"or the geometric conic form, also known as image form:","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"beginaligned\n maxlimits_y in mathbbR^m langle b y rangle\n textsubject to C succeq sum_i=1^m A_i y_i\n y mathsffree\nendaligned","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"In this tutorial, we investigate in which of these two forms a Sum-of-Squares constraint should be written into. Consider the simple example of trying to determine whether the following univariate polynomial is a Sum-of-Squares:","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"import SCS\n@polyvar x\np = (x + 1)^2 * (x + 2)^2\nmodel_scs = Model(SCS.Optimizer)\ncon_ref = @constraint(model_scs, p in SOSCone())\noptimize!(model_scs)","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"As we can see in the log, SCS reports 6 variables and 11 constraints. We can also choose to dualize the problem before it is passed to SCS as follows:","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"using Dualization\nmodel_dual_scs = Model(dual_optimizer(SCS.Optimizer))\n@objective(model_dual_scs, Max, 0.0)\ncon_ref = @constraint(model_dual_scs, p in SOSCone())\noptimize!(model_dual_scs)","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"This time, SCS reports 5 variables and 6 constraints.","category":"page"},{"location":"generated/Getting started/dualization/#Bridges-operating-behind-the-scenes","page":"On the importance of Dualization","title":"Bridges operating behind the scenes","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"The difference comes from the fact that, when designing the JuMP interface of SCS, it was decided that the model would be read in the image form. SCS therefore declares that it only supports free variables, represented in JuMP as variables in MOI.Reals and affine semidefinite constraints, represented in JuMP as MOI.VectorAffineFunction-in-MOI.PositiveSemidefiniteConeTriangle constraints. On the other hand, SumOfSquares gave the model in kernel form so the positive semidefinite (PSD) variables were reformulated as free variables constrained to be PSD using an affine PSD constraints.","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"This transformation is done transparently without warning but it can be inspected using print_active_bridges. As shown below, we can see Unsupported variable: MOI.PositiveSemidefiniteConeTriangle and adding as constraint indicating that PSD variables are not supported and they are added as free variables. Then we have Unsupported constraint: MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle indicating that SCS does not support constraining variables in the PSD cone so it will just convert it into affine expressions in the PSD cone. Of course, this is equivalent but it means that SCS will not exploit this particular structure of the problem hence solving might be less efficient.","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"print_active_bridges(model_scs)","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"With the dual version, we can see that variables in the PSD cone are supported directly hence we don't need that extra conversion.","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"print_active_bridges(model_dual_scs)","category":"page"},{"location":"generated/Getting started/dualization/#In-more-details","page":"On the importance of Dualization","title":"In more details","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"Consider a polynomial","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"p(x) = sum_alpha p_alpha x^alpha","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"a vector of monomials b(x) and the set","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"mathcalA_alpha = (beta gamma) in b(x)^2 mid x^beta x^gamma = x^alpha","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"The constraint encoding the existence of a PSD matrix Q such that p(x) = b(x)' * Q * b(x) can be written in standard conic form as follows:","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"beginaligned\n langle sum_(beta gamma) in mathcalA_alpha e_beta e_gamma^top Q rangle = p_alpha quadforall alpha\n Q succeq 0\nendaligned","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"Given an arbitrary choice of elements in each set mathcalA_alpha: (beta_alpha gamma_alpha) in mathcalA_alpha. It can also equivalently be written in the geometric conic form as follows:","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"beginaligned\n p_alpha e_beta_alpha e_gamma_alpha^top +\n sum_(beta gamma) in mathcalA_alpha setminus (beta_alpha gamma_alpha)\n y_betagamma (e_beta e_gamma - e_beta_alpha e_gamma_alpha^top)^top\n succeq 0\n y_betagamma text free\nendaligned","category":"page"},{"location":"generated/Getting started/dualization/#Should-I-dualize-or-not-?","page":"On the importance of Dualization","title":"Should I dualize or not ?","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"Let's study the evolution of the dimensions m and n of the semidefinite program in two extreme examples and then try to extrapolate from these.","category":"page"},{"location":"generated/Getting started/dualization/#Univariate-case","page":"On the importance of Dualization","title":"Univariate case","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"Suppose p is a univariate polynomial of degree 2d. Then n will be equal to d(d + 1)/2 for both the standard and geometric conic forms. On the other hand, m will be equal to 2d + 1 for the standard conic form and d(d + 1) / 2 - (2d + 1) for the geometric form case. So m grows linearly for the kernel form but quadratically for the image form!","category":"page"},{"location":"generated/Getting started/dualization/#Quadratic-case","page":"On the importance of Dualization","title":"Quadratic case","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"Suppose p is a quadratic form of d variables. Then n will be equal to d for both the standard and geometric conic forms. On the other hand, m will be equal to d(d + 1)/2 for the standard conic form and 0 for the geometric form case. So m grows quadratically for the kernel form but is zero for the image form!","category":"page"},{"location":"generated/Getting started/dualization/#In-general","page":"On the importance of Dualization","title":"In general","text":"","category":"section"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"In general, if s_d is the dimension of the space of polynomials of degree d then m = s_2d for the kernel form and m = s_d(s_d + 1)2 - s_2d for the image form. As a rule of thumb, the kernel form will have a smaller m if p has a low number of variables and low degree and vice versa. Of course, you can always try with and without Dualization and see which one works best.","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"","category":"page"},{"location":"generated/Getting started/dualization/","page":"On the importance of Dualization","title":"On the importance of Dualization","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"EditURL = \"../../tutorials/Sparsity/sign_symmetry.jl\"","category":"page"},{"location":"generated/Sparsity/sign_symmetry/#Sign-symmetry","page":"Sign symmetry","title":"Sign symmetry","text":"","category":"section"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"(Image: ) (Image: ) Adapted from: Example 4 of [L09]","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"[L09] Lofberg, Johan. Pre-and post-processing sum-of-squares programs in practice. IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011.","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"using DynamicPolynomials\n@polyvar x[1:3]","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"We would like to determine whether the following polynomial is a sum-of-squares.","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"poly = 1 + x[1]^4 + x[1] * x[2] + x[2]^4 + x[3]^2","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"In order to do this, we can solve the following Sum-of-Squares program.","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"import CSDP\nsolver = CSDP.Optimizer\nusing SumOfSquares\nfunction sos_check(sparsity)\n model = Model(solver)\n con_ref = @constraint(model, poly in SOSCone(), sparsity = sparsity)\n optimize!(model)\n println(solution_summary(model))\n return gram_matrix(con_ref)\nend\n\ng = sos_check(Sparsity.NoPattern())\ng.basis.monomials","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"As detailed in the Example 4 of [L09], we can exploit the sign symmetry of the polynomial to decompose the large positive semidefinite matrix into smaller ones.","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"g = sos_check(Sparsity.SignSymmetry())\nmonos = [sub.basis.monomials for sub in g.blocks]","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"","category":"page"},{"location":"generated/Sparsity/sign_symmetry/","page":"Sign symmetry","title":"Sign symmetry","text":"This page was generated using Literate.jl.","category":"page"},{"location":"variables/#Polynomial-and-Sum-of-Squares-variables","page":"Variables","title":"Polynomial and Sum-of-Squares variables","text":"","category":"section"},{"location":"variables/#Polynomial-variables","page":"Variables","title":"Polynomial variables","text":"","category":"section"},{"location":"variables/","page":"Variables","title":"Variables","text":"While JuMP allows to create decision variables representing a number whose value needs to be optimized upon by the optimizer, PolyJuMP allows to create polynomial decision variables. In order to do that, we first need to create polynomial variables with the @polyvar macro:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> using DynamicPolynomials # or TypedPolynomials, pick your favorite\n\njulia> @polyvar x y\n(x, y)","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"Note that these should not be confused with JuMP's decision variables which are created using the @variable macro. The polynomial decision variable that will be created need to be parametrized by a polynomial basis of finite size. For instance, if we want to find a quadratic polynomial, we can parametrize it with all monomials of degree between 0 and 2. Generating a vector with such monomials can be achieved through the monomials function:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> X = monomials([x, y], 0:2)\n6-element MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}:\n 1\n y\n x\n y²\n xy\n x²","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"We can now create our polynomial variable p as follows:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> using SumOfSquares\n\njulia> model = Model()\nA JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: NO_OPTIMIZER\nSolver name: No optimizer attached.\n\njulia> @variable(model, p, Poly(X))\n(_[1]) + (_[2])y + (_[3])x + (_[4])y² + (_[5])xy + (_[6])x²","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"This creates a vector of decision variables a and sets p as the scalar product between a and X.","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"Just like with classical JuMP's decision variables, containers of polynomial variables can be created as follows:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> @variable(model, [1:3, 1:4], Poly(X)) # Creates a Matrix\n3×4 Matrix{Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}, VariableRef}}:\n (_[7]) + (_[8])y + (_[9])x + (_[10])y² + (_[11])xy + (_[12])x² … (_[61]) + (_[62])y + (_[63])x + (_[64])y² + (_[65])xy + (_[66])x²\n (_[13]) + (_[14])y + (_[15])x + (_[16])y² + (_[17])xy + (_[18])x² (_[67]) + (_[68])y + (_[69])x + (_[70])y² + (_[71])xy + (_[72])x²\n (_[19]) + (_[20])y + (_[21])x + (_[22])y² + (_[23])xy + (_[24])x² (_[73]) + (_[74])y + (_[75])x + (_[76])y² + (_[77])xy + (_[78])x²\n\njulia> @variable(model, [[:a, :b], -2:2], Poly(X)) # Creates a DenseAxisArray\n2-dimensional DenseAxisArray{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, VariableRef},2,...} with index sets:\n Dimension 1, [:a, :b]\n Dimension 2, -2:2\nAnd data, a 2×5 Matrix{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, VariableRef}}:\n (_[79]) + (_[80])y + (_[81])x + (_[82])y² + (_[83])xy + (_[84])x² … (_[127]) + (_[128])y + (_[129])x + (_[130])y² + (_[131])xy + (_[132])x²\n (_[85]) + (_[86])y + (_[87])x + (_[88])y² + (_[89])xy + (_[90])x² (_[133]) + (_[134])y + (_[135])x + (_[136])y² + (_[137])xy + (_[138])x²\n\njulia> @variable(model, [i=1:3, j=i:3], Poly(X)) # Creates a SparseAxisArray\nJuMP.Containers.SparseAxisArray{Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}, VariableRef}, 2, Tuple{Int64, Int64}} with 6 entries:\n [1, 1] = (_[139]) + (_[140])*y + (_[141])*x + (_[142])*y^2 + (_[143])*x*y + (_[144])*x^2\n [1, 2] = (_[145]) + (_[146])*y + (_[147])*x + (_[148])*y^2 + (_[149])*x*y + (_[150])*x^2\n [1, 3] = (_[151]) + (_[152])*y + (_[153])*x + (_[154])*y^2 + (_[155])*x*y + (_[156])*x^2\n [2, 2] = (_[157]) + (_[158])*y + (_[159])*x + (_[160])*y^2 + (_[161])*x*y + (_[162])*x^2\n [2, 3] = (_[163]) + (_[164])*y + (_[165])*x + (_[166])*y^2 + (_[167])*x*y + (_[168])*x^2\n [3, 3] = (_[169]) + (_[170])*y + (_[171])*x + (_[172])*y^2 + (_[173])*x*y + (_[174])*x^2","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"For more flexibility, polynomials parametrized by decision variables can also be created \"by hand\" for instance as follows:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> @variable(model, α)\nα\n\njulia> @variable(model, β)\nβ\n\njulia> p = α*x^2 + (α+β)*y^2*x + β*y^3\n(α)x² + (β)y³ + (α + β)xy²","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"The coefficients of the polynomial can even be quadratic, e.g.","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> p = (3α^2+β)*x^2 + (α*β+2β)*y^2*x + β*y^3\n(3 α² + β)x² + (β)y³ + (α*β + 2 β)xy²","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"Let me stress again the distinction between α and β which are decision variables and x and y which are polynomial variables.","category":"page"},{"location":"variables/#Nonnegative-polynomial-variables","page":"Variables","title":"Nonnegative polynomial variables","text":"","category":"section"},{"location":"variables/","page":"Variables","title":"Variables","text":"In order to create a sum-of-squares polynomial variable, the syntax is exactly the same except SOSPoly should be used instead of Poly. For instance, the following code creates a 3 times 4 matrix of sum-of-squares polynomial variables:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> @variable(model, [1:2], SOSPoly(X))\n2-element Vector{GramMatrix{VariableRef, MonomialBasis{Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}, MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}}, AffExpr, SymMatrix{VariableRef}}}:\n GramMatrix with row/column basis:\n MonomialBasis([1, y, x, y^2, x*y, x^2])\nAnd entries in a 6×6 SymMatrix{VariableRef}:\n _[177] _[178] _[180] _[183] _[187] _[192]\n _[178] _[179] _[181] _[184] _[188] _[193]\n _[180] _[181] _[182] _[185] _[189] _[194]\n _[183] _[184] _[185] _[186] _[190] _[195]\n _[187] _[188] _[189] _[190] _[191] _[196]\n _[192] _[193] _[194] _[195] _[196] _[197]\n GramMatrix with row/column basis:\n MonomialBasis([1, y, x, y^2, x*y, x^2])\nAnd entries in a 6×6 SymMatrix{VariableRef}:\n _[198] _[199] _[201] _[204] _[208] _[213]\n _[199] _[200] _[202] _[205] _[209] _[214]\n _[201] _[202] _[203] _[206] _[210] _[215]\n _[204] _[205] _[206] _[207] _[211] _[216]\n _[208] _[209] _[210] _[211] _[212] _[217]\n _[213] _[214] _[215] _[216] _[217] _[218]","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"There is however an important difference between the meaning of the vector of monomials X between Poly and SOSPoly. For SOSPoly, it creates a positive semidefinite matrix of variables Q and sets p as the value of X' * Q * X. That is, for instance, if X contains all the monomials of degree 2, then all the monomials of p will have degree 4 (i.e. p will be a quartic form).","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"Similarly, to create diagonally-dominant-sum-of-squares polynomial variables (see [Definition 3.1, AM17]), use DSOSPoly(X). This creates a diagonally dominant matrix of variables Q and sets the polynomial variables as the value of X' * Q * X.","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"Finally, to create scaled-diagonally-dominant-sum-of-squares polynomial variables (see [Definition 3.2, AM17]), use SDSOSPoly(X). This creates a scaled diagonally dominant matrix of variables Q and sets the polynomial variables as the value of X' * Q * X.","category":"page"},{"location":"variables/#Choosing-a-polynomial-basis","page":"Variables","title":"Choosing a polynomial basis","text":"","category":"section"},{"location":"variables/","page":"Variables","title":"Variables","text":"In the previous section, we show how to create polynomial variables from a monomial basis. However, the monomial basis is only a particular case of polynomial basis and while using a different basis of the same space of polynomial is would give an equivalent program, it might be more stable numerically (see [Section 3.1.5, BPT12]).","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"For instance, creating an univariate cubic polynomial variable p using the Chebyshev basis can be done as follows:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> cheby_basis = FixedPolynomialBasis([1, x, 2x^2-1, 4x^3-3x])\nFixedPolynomialBasis([1, x, -1 + 2x², -3x + 4x³])\n\njulia> @variable(model, variable_type=Poly(cheby_basis))\n(_[219] - _[221]) + (_[220] - 3 _[222])x + (2 _[221])x² + (4 _[222])x³","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"and to create a quadratic form variable q using the scaled monomial basis (see [Section 3.1.5, BPT12]), use the following:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> X = monomials([x, y], 2)\n3-element MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}:\n y²\n xy\n x²\n\njulia> scaled_basis = ScaledMonomialBasis(X)\nScaledMonomialBasis([y², xy, x²])\n\njulia> @variable(model, variable_type=Poly(scaled_basis))\n(_[223])y² + (1.4142135623730951 _[224])xy + (_[225])x²","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"which is equivalent to","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"julia> scaled_basis = FixedPolynomialBasis([x^2, √2*x*y, y^2])\nFixedPolynomialBasis([x², 1.4142135623730951xy, y²])\n\njulia> @variable(model, variable_type=Poly(scaled_basis))\n(_[228])y² + (1.4142135623730951 _[227])xy + (_[226])x²","category":"page"},{"location":"variables/#References","page":"Variables","title":"References","text":"","category":"section"},{"location":"variables/","page":"Variables","title":"Variables","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.","category":"page"},{"location":"variables/#Reference","page":"Variables","title":"Reference","text":"","category":"section"},{"location":"variables/","page":"Variables","title":"Variables","text":"SumOfSquares.PolyJuMP.Poly","category":"page"},{"location":"variables/#PolyJuMP.Poly","page":"Variables","title":"PolyJuMP.Poly","text":"struct Poly{PB<:AbstractPolynomialBasis} <: AbstractPoly\n polynomial_basis::PB\nend\n\nPolynomial variable v^top p where v is a vector of new decision variables and p is a vector of polynomials for the basis polynomial_basis.\n\n\n\n\n\n","category":"type"},{"location":"variables/","page":"Variables","title":"Variables","text":"Variable bridges:","category":"page"},{"location":"variables/","page":"Variables","title":"Variables","text":"SumOfSquares.Bridges.Variable.ScaledDiagonallyDominantBridge","category":"page"},{"location":"variables/#SumOfSquares.Bridges.Variable.ScaledDiagonallyDominantBridge","page":"Variables","title":"SumOfSquares.Bridges.Variable.ScaledDiagonallyDominantBridge","text":"struct ScaledDiagonallyDominantBridge{T} <: MOI.Bridges.Variable.AbstractBridge\n side_dimension::Int\n variables::Vector{Vector{MOI.VariableIndex}}\n constraints::Vector{MOI.ConstraintIndex{\n MOI.VectorOfVariables, SOS.PositiveSemidefinite2x2ConeTriangle}}\nend\n\nA matrix is SDD iff it is the sum of psd matrices Mij that are zero except for entries ii, ij and jj [Lemma 9, AM17]. This bridge substitute the constrained variables in SOS.ScaledDiagonallyDominantConeTriangle into a sum of constrained variables in SOS.PositiveSemidefinite2x2ConeTriangle.\n\n[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.\n\n\n\n\n\n","category":"type"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"EditURL = \"../../tutorials/Getting started/circle.jl\"","category":"page"},{"location":"generated/Getting started/circle/#Nonnegative-over-a-variety","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"","category":"section"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"(Image: ) (Image: )","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"The polynomial 1 - y^2 is nonnegative for all y in the unit circle. This can be verified using Sum-of-Squares.","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"using DynamicPolynomials\nusing SumOfSquares\n@polyvar x y\nS = @set x^2 + y^2 == 1","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"We need to pick an SDP solver, see here for a list of the available choices. The domain over which the nonnegativity of 1 - y^2 should be certified is specified through the domain keyword argument.","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"import CSDP\nmodel = SOSModel(CSDP.Optimizer)\nset_silent(model)\ncon_ref = @constraint(model, 1 - y^2 >= 0, domain = S)\noptimize!(model)","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"We can see that the model was feasible:","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"solution_summary(model)","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"The certificate can be obtained as follows:","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"sos_decomposition(con_ref, 1e-6)","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"It returns x^2 which is a valid certificate as: $ 1 - y^2 \\equiv x^2 \\pmod{x^2 + y^2 - 1} $","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"","category":"page"},{"location":"generated/Getting started/circle/","page":"Nonnegative over a variety","title":"Nonnegative over a variety","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"EditURL = \"../../tutorials/Systems and Control/barrier_certificate.jl\"","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/#Barrier-certificates-for-collision-avoidance","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"","category":"section"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Adapted from: Example 2 of \"Engineering applications of SOS polynomials\" by Georgina Hall, from the 2019 AMS Short Course on Sum of Squares: Theory and Applications Implementation by: Hugo Tadashi Kussaba","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"using DynamicPolynomials\n@polyvar x[1:2]\n\nusing SumOfSquares\nusing CSDP","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = SOSModel(solver);\nnothing #hide","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"We define below the vector field textdxtextdt = f","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"f = [ x[2],\n -x[1] + (1/3)*x[1]^3 - x[2]]","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Semi-algebraic function describing the unsafe set 𝒳ᵤ","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"g₁ = -(x[1]+1)^2 - (x[2]+1)^2 + 0.16 # 𝒳ᵤ = {x ∈ R²: g₁(x) ≥ 0}","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Semi-algebraic function describing the initial set 𝒳₀","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"h₁ = -(x[1]-1.5)^2 - x[2]^2 + 0.25 # 𝒳₀ = {x ∈ R²: h₁(x) ≥ 0}","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Define SOS barrier function B","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"monos = monomials(x, 0:4)\n@variable(model, B, Poly(monos))","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Define barrier certificate constraints using SOS relaxation","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"B(x) > 0 for all x ∈ 𝒳ᵤ","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"ε = 0.001\n@constraint(model, B >= ε, domain = @set(g₁ >= 0))","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"B(x) ≤ 0 for all x ∈ 𝒳₀","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"@constraint(model, B <= 0, domain = @set(h₁ >= 0))","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Ḃ(x) ≤ 0 for all x ∈ R²","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"using LinearAlgebra # Needed for `dot`\ndBdt = dot(differentiate(B, x), f)\n@constraint(model, -dBdt >= 0)","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"The model is ready to be optimized by the solver:","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"JuMP.optimize!(model)","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"We verify that the solver has found a feasible solution:","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"JuMP.primal_status(model)","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"Plot the phase plot with the 0-level set of the barrier function, and the boundary of the initial and unsafe sets","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"import DifferentialEquations, Plots, ImplicitPlots\nfunction phase_plot(f, B, g₁, h₁, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5())\n X₀plot = ImplicitPlots.implicit_plot(h₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label=\"X₀\", linecolor=:blue)\n Xᵤplot = ImplicitPlots.implicit_plot!(g₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label=\"Xᵤ\", linecolor=:teal)\n Bplot = ImplicitPlots.implicit_plot!(B; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label=\"B = 0\", linecolor=:red)\n Plots.plot(X₀plot)\n Plots.plot!(Xᵤplot)\n Plots.plot!(Bplot)\n ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f]\n ∇pt(v, p, t) = ∇(v[1], v[2])\n function traj(v0)\n tspan = (0.0, Δt)\n prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan)\n return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8)\n end\n ticks = -5:0.5:5\n X = repeat(ticks, 1, length(ticks))\n Y = X'\n Plots.quiver!(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5)\n for x0 in X0\n Plots.plot!(traj(x0), vars=(1, 2), label = nothing)\n end\n Plots.plot!(xlims = (-2, 3), ylims = (-2.5, 2.5))\nend\n\nphase_plot(f, value(B), g₁, h₁, 10, 30.0, [[x1, x2] for x1 in 1.2:0.2:1.7, x2 in -0.35:0.1:0.35])","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"","category":"page"},{"location":"generated/Systems and Control/barrier_certificate/","page":"Barrier certificates for collision avoidance","title":"Barrier certificates for collision avoidance","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"EditURL = \"../../tutorials/Systems and Control/lyapunov_function_search.jl\"","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/#Lyapunov-Function-Search","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"","category":"section"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"(Image: ) (Image: ) Adapted from: SOSTOOLS' SOSDEMO2 (See Section 4.2 of SOSTOOLS User's Manual)","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"using DynamicPolynomials\n@polyvar x[1:3]","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We define below the vector field textdxtextdt = f","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"f = [-x[1]^3 - x[1] * x[3]^2,\n -x[2] - x[1]^2 * x[2],\n -x[3] - 3x[3] / (x[3]^2 + 1) + 3x[1]^2 * x[3]]","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We need to pick an SDP solver, see here for a list of the available choices. We use SOSModel instead of Model to be able to use the >= syntax for Sum-of-Squares constraints.","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"using SumOfSquares\nusing CSDP\nsolver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)\nmodel = SOSModel(solver);\nnothing #hide","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We are searching for a Lyapunov function V(x) with monomials x_1^2, x_2^2 and x_3^2. We first define the monomials to be used for the Lyapunov function:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"monos = x.^2","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We now define the Lyapunov function as a polynomial decision variable with these monomials:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"@variable(model, V, Poly(monos))","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We need to make sure that the Lyapunov function is strictly positive. We can do this with a constraint V(x) ge epsilon (x_1^2 + x_2^2 + x_3^2), let's pick epsilon = 1:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"@constraint(model, V >= sum(x.^2))","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We now compute textdVtextdx cdot f.","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"using LinearAlgebra # Needed for `dot`\ndVdt = dot(differentiate(V, x), f)","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"The denominator is x3^2 + 1 is strictly positive so the sign of dVdt is the same as the sign of its numerator.","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"P = dVdt.num","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"Hence, we constrain this numerator to be nonnegative:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"@constraint(model, P <= 0)","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"The model is ready to be optimized by the solver:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"JuMP.optimize!(model)","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We verify that the solver has found a feasible solution:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"JuMP.primal_status(model)","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"We can now obtain this feasible solution with:","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"value(V)","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"","category":"page"},{"location":"generated/Systems and Control/lyapunov_function_search/","page":"Lyapunov Function Search","title":"Lyapunov Function Search","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"EditURL = \"../../tutorials/Symmetry/dihedral.jl\"","category":"page"},{"location":"generated/Symmetry/dihedral/#Dihedral-symmetry-of-the-Robinson-form","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"","category":"section"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"(Image: ) (Image: ) Adapted from: Example 5.4 of [GP04]","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"[GP04] Gatermann, Karin and Parrilo, Pablo A. Symmetry groups, semidefinite programs, and sums of squares. Journal of Pure and Applied Algebra 192.1-3 (2004): 95-128.","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"We start by defining the Dihedral group of order 8. This group is isomorphic to the following permutation group:","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"using PermutationGroups\nd = perm\"(1, 2, 3, 4)\"\nc = perm\"(1, 3)\"\nG = PermGroup([c, d])","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"We could rely on this isomorphism to define this group. However, in order to illustrate how to do symmetry reduction with a custom group, we show in this example what should be implemented to define a new group.","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"import GroupsCore\n\nstruct DihedralGroup <: GroupsCore.Group\n n::Int\nend\n\nstruct DihedralElement <: GroupsCore.GroupElement\n n::Int\n reflection::Bool\n id::Int\nend","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"Implementing GroupsCore API:","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"Base.one(G::DihedralGroup) = DihedralElement(G.n, false, 0)\n\nBase.eltype(::Type{DihedralGroup}) = DihedralElement\nBase.IteratorSize(::Type{DihedralGroup}) = Base.HasLength()\n\nfunction Base.iterate(G::DihedralGroup, prev::DihedralElement=DihedralElement(G.n, false, -1))\n if prev.id + 1 >= G.n\n if prev.reflection\n return nothing\n else\n next = DihedralElement(G.n, true, 0)\n end\n else\n next = DihedralElement(G.n, prev.reflection, prev.id + 1)\n end\n return next, next\nend\n\nGroupsCore.order(::Type{T}, G::DihedralGroup) where {T} = convert(T, 2G.n)\nGroupsCore.gens(G::DihedralGroup) = [DihedralElement(G.n, false, 1), DihedralElement(G.n, true, 0)]","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"Base.rand not needed for our purposes here","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"Base.parent(g::DihedralElement) = DihedralGroup(g.n)\nfunction Base.:(==)(g::DihedralElement, h::DihedralElement)\n return g.n == h.n && g.reflection == h.reflection && g.id == h.id\nend\n\nfunction Base.inv(el::DihedralElement)\n if el.reflection || iszero(el.id)\n return el\n else\n return DihedralElement(el.n, false, el.n - el.id)\n end\nend\nfunction Base.:*(a::DihedralElement, b::DihedralElement)\n a.n == b.n || error(\"Cannot multiply elements from different Dihedral groups\")\n id = mod(a.reflection ? a.id - b.id : a.id + b.id, a.n)\n return DihedralElement(a.n, a.reflection != b.reflection, id)\nend\n\nBase.copy(a::DihedralElement) = DihedralElement(a.n, a.reflection, a.id)","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"optional functions:","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"function GroupsCore.order(el::DihedralElement)\n if el.reflection\n return 2\n else\n if iszero(el.id)\n return 1\n else\n return div(el.n, gcd(el.n, el.id))\n end\n end\nend","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"The Robinson form is invariant under the following action of the Dihedral group on monomials: The action of each element of the groups is to map the variables x, y to:","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"id rotation reflection\n0 x, y y, x\n1 -y, x -x, y\n2 -x, -y -y, -x\n3 y, -x x, -y","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"using SumOfSquares\nusing DynamicPolynomials\n@polyvar x y\nstruct DihedralAction <: Symmetry.OnMonomials end\nimport SymbolicWedderburn\nSymbolicWedderburn.coeff_type(::DihedralAction) = Float64\nfunction SymbolicWedderburn.action(::DihedralAction, el::DihedralElement, mono::AbstractMonomial)\n if iseven(el.reflection + el.id)\n var_x, var_y = x, y\n else\n var_x, var_y = y, x\n end\n sign_x = 1 <= el.id <= 2 ? -1 : 1\n sign_y = 2 <= el.id ? -1 : 1\n return mono([x, y] => [sign_x * var_x, sign_y * var_y])\nend\n\npoly = x^6 + y^6 - x^4 * y^2 - y^4 * x^2 - x^4 - y^4 - x^2 - y^2 + 3x^2 * y^2 + 1","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"We can verify that poly is indeed invariant under the action of each element of the group as follows.","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"G = DihedralGroup(4)\nfor g in G\n @show SymbolicWedderburn.action(DihedralAction(), g, poly)\nend","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"We can exploit this symmetry for reducing the problem using the SymmetricIdeal certificate as follows:","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"import CSDP\nfunction solve(G)\n solver = CSDP.Optimizer\n model = Model(solver)\n @variable(model, t)\n @objective(model, Max, t)\n pattern = Symmetry.Pattern(G, DihedralAction())\n con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern)\n optimize!(model)\n @show value(t)\n\n\n for g in gram_matrix(con_ref).blocks\n println(g.basis.polynomials)\n end\nend\nsolve(G)","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"We notice that we indeed find -3825/4096 and that symmetry was exploited.","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"","category":"page"},{"location":"generated/Symmetry/dihedral/","page":"Dihedral symmetry of the Robinson form","title":"Dihedral symmetry of the Robinson form","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"EditURL = \"../../tutorials/Polynomial Optimization/polynomial_optimization.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#Polynomial-Optimization","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#Introduction","page":"Polynomial Optimization","title":"Introduction","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Consider the polynomial optimization problem (Lasserre, 2009; Example 2.2) of minimizing the polynomial x^3 - x^2 + 2xy - y^2 + y^3 over the polyhedron defined by the inequalities x ge 0 y ge 0 and x + y geq 1.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"using DynamicPolynomials\n@polyvar x y\np = x^3 - x^2 + 2x*y -y^2 + y^3\nusing SumOfSquares\nS = @set x >= 0 && y >= 0 && x + y >= 1\np(x=>1, y=>0), p(x=>1//2, y=>1//2), p(x=>0, y=>1)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#Local-search","page":"Polynomial Optimization","title":"Local search","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"A local solver only uses the local information given by the the value, gradient and hessian of the objective function and constraints at a given solution. When it converges, it therefore only guarantees that the found solution is a local minimum. In this example, the optimal solutions are (x y) = (1 0) and (x y) = (0 1) with objective value 0 but Ipopt only finds the local minimum (12 12) with objective value 14.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"import Ipopt\nmodel = Model(Ipopt.Optimizer)\n@variable(model, a >= 0)\n@variable(model, b >= 0)\n@constraint(model, a + b >= 1)\n@NLobjective(model, Min, a^3 - a^2 + 2a*b - b^2 + b^3)\noptimize!(model)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"As we can see below, the termination status is LOCALLY_SOLVED and not of OPTIMAL because Ipopt only guarantees local optimality.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"solution_summary(model)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Indeed, the solution found is not globally optimal:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"value(a), value(b)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Note that the problem can be written equivalently as follows using registered functions. The difference is that the gradient and hessian will be computed via the Symbolic Differentiation provided by MultivariatePolynomials instead of JuMP's Automatic Differentiation:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"f(a, b) = p(x => a, y => b)\n∇p = differentiate(p, [x, y])\nfunction ∇f(g, a, b)\n for i in eachindex(g)\n g[i] = ∇p[i](x => a, y => b)\n end\nend\n∇²p = differentiate(∇p, [x, y])\nfunction ∇²f(H, a, b)\n for j in axes(∇²p, 2)\n for i in j:size(∇²p, 1)\n H[i, j] = ∇²p[i, j](x => a, y => b)\n end\n end\nend\nusing Ipopt\ngmodel = Model(Ipopt.Optimizer)\n@variable(gmodel, a >= 0)\n@variable(gmodel, b >= 0)\n@constraint(gmodel, a + b >= 1)\nregister(gmodel, :f, 2, f, ∇f, ∇²f)\n@NLobjective(gmodel, Min, f(a, b))\noptimize!(gmodel)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Even if we have the algebraic expressions of gradient and hessian, Ipopt is not using these symbolic expressions but only local information hence it can still only provide local guarantees:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"solution_summary(gmodel)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"and the same solution is found:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"value(a), value(b)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#Sum-of-Squares-approach","page":"Polynomial Optimization","title":"Sum-of-Squares approach","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"import SCS\nscs = SCS.Optimizer\nimport Dualization\ndual_scs = Dualization.dual_optimizer(scs)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following program searches for the largest lower bound and finds zero.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"model = SOSModel(dual_scs)\n@variable(model, α)\n@objective(model, Max, α)\n@constraint(model, c3, p >= α, domain = S)\noptimize!(model)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"This time, the termination status is OPTIMAL but this does not necessarily mean that we found the optimal solution to the polynomial optimization problem. This only means that CSDP founds an optimal solution to the Sum-of-Squares relaxation.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"solution_summary(model)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The feasibility of the primal solution guarantees that the objective value 0 is a lower bound to the polynomial optimization problem. The optimality means that it's the best lower bound we can get (at this degree of the hierarcy). Using the solution (12 12) found by Ipopt of objective value 14 and this certificate of lower bound 0 we know that the optimal objective value is in the interval 0 14 but we still do not know what it is (if we consider that we did not try the solutions (1 0) and (0 1) as done in the introduction). If the dual of the constraint c3 was atomic, its atoms would have given optimal solutions of objective value 0 but that is not the case.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"ν3 = moment_matrix(c3)\natomic_measure(ν3, 1e-3) # Returns nothing as the dual is not atomic","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Fortunately, there is a hierarchy of programs with increasingly better bounds that can be solved until we get one with atom dual variables. This comes from the way the Sum-of-Squares constraint with domain S is formulated. The polynomial p - alpha is guaranteed to be nonnegative over the domain S if there exists Sum-of-Squares polynomials s_0, s_1, s_2, s_3 such that","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"p - alpha = s_0 + s_1 x + s_2 y + s_3 (x + y - 1)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Indeed, in the domain S, x, y and x + y - 1 are nonnegative so the right-hand side is a sum of squares hence is nonnegative. Once the degrees of s_1, s_2 and s_3 have been decided, the degree needed for s_0 will be determined but we have a freedom in choosing the degrees of s_1, s_2 and s_3. By default, they are chosen so that the degrees of s_1 x, s_2 y and s_3 (x + y - 1) match those of p - alpha but this can be overwritten using the maxdegree keyword argument.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#The-maxdegree-keyword-argument","page":"Polynomial Optimization","title":"The maxdegree keyword argument","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The maximum total degree (i.e. maximum sum of the exponents of x and y) of the monomials of p is 3 so the constraint in the program above is equivalent to @constraint(model, p >= α, domain = S, maxdegree = 3). That is, since x, y and x + y - 1 have total degree 1, the sum of squares polynomials s_1, s_2 and s_3 have been chosen with maximum total degree 2. Since these polynomials are sums of squares, their degree must be even so the next maximum total degree to try is 4. For this reason, the keywords maxdegree = 4 and maxdegree = 5 have the same effect in this example. In general, if the polynomials in the domain are not all odd or all even, each value of maxdegree has a different effect in the choice of the maximum total degree of some s_i.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"model = SOSModel(dual_scs)\n@variable(model, α)\n@objective(model, Max, α)\n@constraint(model, c4, p >= α, domain = S, maxdegree = 4)\noptimize!(model)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"We can see that the basis of the moment matrix didn't increase:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"moment_matrix(c4)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"This is because of the Newton polytope reduction that determined that gram matrix will be zero for these degrees so it reduced the problem back to the equivalent of maxdegree 3 Let's turn this off with newton_polytope = nothing","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"function sos(solver, deg)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = S, maxdegree = deg, newton_polytope = nothing)\n optimize!(model)\n return model\nend\ndual_model4 = sos(dual_scs, 4)\nnothing #hide","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"We see that the lower bound is still 0:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"solution_summary(dual_model4)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Let's now look at which solution we can extract from the moment matrix:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"dual_ν4 = moment_matrix(dual_model4[:c])","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Looking at the singular values, 4 seems to be a reasonable rank:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"using LinearAlgebra\nsvdvals(Matrix(dual_ν4.Q))","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The solution we extract is (0.5, 0.5) which is the solution found by Ipopt:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"atomic_measure(dual_ν4, FixedRank(4))","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"This process is quite sensitive numerically so let's try to solve it without dualization as well:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"model4 = sos(scs, 4)\nnothing #hide","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"We see that the lower bound is again 0:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"solution_summary(model4)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The moment matrix is the following","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"ν4 = moment_matrix(model4[:c])","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"Looking at the singular values, 3 seems to be a reasonable rank:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"svdvals(Matrix(ν4.Q))","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"This time, the dual variable is atomic as it is the moments of the measure 05 delta(x-1 y) + 05 delta(x y-1) where delta(x y) is the dirac measure centered at (0 0). Therefore the program provides both a certificate that 0 is a lower bound and a certificate that it is also an upper bound since it is attained at the global minimizers (1 0) and (0 1).","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"atomic_measure(ν4, FixedRank(3))","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#A-deeper-look-into-atom-extraction","page":"Polynomial Optimization","title":"A deeper look into atom extraction","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The moment matrix is transformed into a system of polynomials equations whose solutions give the atoms. This transformation uses the SVD decomposition of the moment matrix and discards the equations corresponding to the lowest singular values. When this system of equation has an infinite number of solutions, atomic_measure concludes that the measure is not atomic. For instance, with maxdegree = 3, we obtain the system x + y = 1 which contains a whole line of solution. This explains atomic_measure returned nothing.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"ν3 = moment_matrix(c3)\nSumOfSquares.MultivariateMoments.compute_support!(ν3, LeadingRelativeRankTol(1e-3))","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"With maxdegree = 4, we obtain the system","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"beginaligned\n x + y = 1\n y^2 = y\n xy = 0\n -y + y^2 - x*y = 0\n y^2 - 2y + 1 = x^2\nendaligned","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"ν4 = moment_matrix(model4[:c])\nSumOfSquares.MultivariateMoments.compute_support!(ν4, FixedRank(3))","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"This system can be reduced to the equivalent system","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"beginaligned\n x + y = 1\n y^2 = y\nendaligned","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"which has the solutions (0 1) and (1 0).","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"SemialgebraicSets.compute_gröbner_basis!(ideal(ν4.support))\nν4.support","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The solutions of this system then give the minimizers","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"collect(ν4.support)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The function atomic_measure then reuses the matrix of moments to find the weights 12, 12 corresponding to the diracs centered respectively at (0 1) and (1 0). This details how the function obtained the result 05 delta(x-1 y) + 05 delta(x y-1) given in the previous section.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/#HomotopyContinuation","page":"Polynomial Optimization","title":"HomotopyContinuation","text":"","category":"section"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"As discussed in the previous section, the atom extraction relies on the solution of a system of algebraic equations. The atomic_measure function takes an optional algebraic_solver argument that is used to solve this system of equation. If no solver is provided, the default solver of SemialgebraicSets.jl is used which currently computes the Gröbner basis, then the multiplication matrices and then the Schur decomposition of a random combination of these matrices. As the system of equations is obtained from a numerical solution and is represented using floating point coefficients, homotopy continuation is recommended as it is more numerically robust than Gröbner basis computation. The following uses homotopy continuation to solve the system of equations.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"using HomotopyContinuation\nalgebraic_solver = SemialgebraicSetsHCSolver(; excess_residual_tol = 1e-1, real_tol = 1e-1, compile = false)\natomic_measure(ν4, FixedRank(3), Echelon(), algebraic_solver)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"As the system has 3 equations for 2 variables and the coefficients of the equations are to be treated with tolerance since they originate from the solution of an SDP, we need to set excess_residual_tol and real_tol to a high tolerance otherwise, HomotopyContinuation would consider that there is no solution. Indeed, as the system is overdetermined (it has more equations than variables) HomotopyContinuation expects to have excess solution hence it filters out excess solution among the solution found. It determines which solution are in excess by comparing the infinity norm of the residuals of the equations at the solution with excess_residual_tol. It also filters out solution for which the absolute value of the imaginary part of one of the entry is larger than real_tol and strips out the imaginary part. The raw solutions obtained by HomotopyContinuation can be obtained as follows:","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"F = HomotopyContinuation.System(ν4.support)\nres = HomotopyContinuation.solve(F, algebraic_solver.options...)\npath_results(res)","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"The printed residual above shows why 1e-1 allows to filter how the 2 actual solutions from the 2 excess solutions.","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"","category":"page"},{"location":"generated/Polynomial Optimization/polynomial_optimization/","page":"Polynomial Optimization","title":"Polynomial Optimization","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"EditURL = \"../../tutorials/Polynomial Optimization/min_univariate.jl\"","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/#Maximizing-as-minimum","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"","category":"section"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"(Image: ) (Image: ) Adapted from: (Floudas et al., 1999; Section 4.10), (Laurent, 2008; Example 6.23) and (Lasserre, 2009; Table 5.1)","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/#Introduction","page":"Maximizing as minimum","title":"Introduction","text":"","category":"section"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"Consider the polynomial optimization problem from (Floudas et al., 1999; Section 4.10) of minimizing the linear function -x_1 - x_2 over the basic semialgebraic set defined by the inequalities x_2 le 2x_1^4 - 8x_1^3 + 8x_1^2 + 2, x_2 le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36 and the box constraints 0 le x_1 le 3 and 0 le x_2 le 4,","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"using DynamicPolynomials\n@polyvar x[1:2]\np = -sum(x)\nusing SumOfSquares\nf1 = 2x[1]^4 - 8x[1]^3 + 8x[1]^2 + 2\nf2 = 4x[1]^4 - 32x[1]^3 + 88x[1]^2 - 96x[1] + 36\nK = @set x[1] >= 0 && x[1] <= 3 && x[2] >= 0 && x[2] <= 4 && x[2] <= f1 && x[2] <= f2","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"As we can observe below, the bounds on x[2] could be dropped and optimization problem is equivalent to the maximization of min(f1, f2) between 0 and 3.","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"xs = range(0, stop = 3, length = 100)\nusing Plots\nplot(xs, f1.(xs), label = \"f1\")\nplot!(xs, f2.(xs), label = \"f2\")\nplot!(xs, 4 * ones(length(xs)), label = nothing)","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"We will now see how to find the optimal solution using Sum of Squares Programming. We first need to pick an SDP solver, see here for a list of the available choices.","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"import Clarabel\nsolver = Clarabel.Optimizer","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"A Sum-of-Squares certificate that p ge alpha over the domain S, ensures that alpha is a lower bound to the polynomial optimization problem. The following function searches for the largest lower bound and finds zero using the dth level of the hierarchy`.","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"function solve(d)\n model = SOSModel(solver)\n @variable(model, α)\n @objective(model, Max, α)\n @constraint(model, c, p >= α, domain = K, maxdegree = d)\n optimize!(model)\n println(solution_summary(model))\n return model\nend","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"The first level of the hierarchy gives a lower bound of -7`","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"model4 = solve(4)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"The second level improves the lower bound","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"model5 = solve(5)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"The third level finds the optimal objective value as lower bound...","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"model7 = solve(7)\nnothing # hide","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"...and proves it by exhibiting the minimizer.","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"ν7 = moment_matrix(model7[:c])\nη = atomic_measure(ν7, 1e-3) # Returns nothing as the dual is not atomic","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"We can indeed verify that the objective value at x_opt is equal to the lower bound.","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"x_opt = η.atoms[1].center\np(x_opt)","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"We can see visualize the solution as follows:","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"scatter!([x_opt[1]], [x_opt[2]], markershape = :star, label = nothing)","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"","category":"page"},{"location":"generated/Polynomial Optimization/min_univariate/","page":"Maximizing as minimum","title":"Maximizing as minimum","text":"This page was generated using Literate.jl.","category":"page"},{"location":"bibliography/#Bibliography","page":"Bibliography","title":"Bibliography","text":"","category":"section"},{"location":"bibliography/","page":"Bibliography","title":"Bibliography","text":"Floudas, C. A.; Pardalos, P. M.; Adjiman, C. S.; Esposito, W. R.; Gümüş, Z. H.; Harding, S. T.; Klepeis, J. L.; Meyer, C. A. and Schweiger, C. A. (1999). Handbook of Test Problems in Local and Global Optimization (Springer US).\n\n\n\nHesse, R. (1973). A Heuristic Search Procedure for Estimating a Global Solution of Nonconvex Programming Problems. Operations Research 21, 1267–1280.\n\n\n\nLasserre, J. B. (2009). Moments, Positive Polynomials and Their Applications (Imperial College Press).\n\n\n\nLaurent, M. (2008). Sums of Squares, Moment Matrices and Optimization Over Polynomials. In: The IMA Volumes in Mathematics and its Applications (Springer New York); pp. 157–270.\n\n\n\n","category":"page"},{"location":"#SumOfSquares-–-Sum-of-Squares-Programming-for-Julia","page":"Index","title":"SumOfSquares –- Sum of Squares Programming for Julia","text":"","category":"section"},{"location":"","page":"Index","title":"Index","text":"SumOfSquares implements Sum of Squares reformulation for PolyJuMP, enabling the creation of sum of squares variables and constraints in JuMP.","category":"page"},{"location":"","page":"Index","title":"Index","text":"The polynomial can be represented by any library implementing the MultivariatePolynomial.jl interface. That is, you can currently choose between DynamicPolynomials and TypedPolynomials. As a rule of thumb, if you know at compile time (or at the time you are writing your code), the number of variable and that this number is small, use TypedPolynomials, otherwise, use DynamicPolynomials.","category":"page"},{"location":"#Contents","page":"Index","title":"Contents","text":"","category":"section"},{"location":"","page":"Index","title":"Index","text":"Pages = [\"sumofsquares.md\", \"variables.md\", \"constraints.md\"]\nDepth = 2","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"EditURL = \"../../tutorials/Extension/univariate_solver.jl\"","category":"page"},{"location":"generated/Extension/univariate_solver/#Univariate-Solver","page":"Univariate Solver","title":"Univariate Solver","text":"","category":"section"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"(Image: ) (Image: ) Contributed by: Benoît Legat","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"When using an SDP solver, the Sum-of-Squares constraint is bridged into a semidefinite constraint. This reformulation is done only if the solver does not support the Sum-of-Squares constraint. We show in this tutorial how to define a solver that supports such constraint. The same model with be then solved with or without reformulation depending on the solver.","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"We consider a solver that would support finding the SOS decomposition of nonnegative univariate polynomials.","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"module MyUnivariateSolver\n\nimport LinearAlgebra\nimport MathOptInterface as MOI\nimport MultivariatePolynomials as MP\nimport SumOfSquares as SOS\n\nfunction decompose(p::MP.AbstractPolynomial, tol=1e-6)\n vars = MP.effective_variables(p)\n if length(vars) != 1\n error(\"$p is not univariate\")\n end\n x = first(vars)\n lead = MP.leading_coefficient(p)\n if !isone(lead)\n p = p / lead\n end\n deg = MP.maxdegree(p)\n if isodd(deg)\n return\n end\n d = div(deg, 2)\n companion = zeros(2d, 2d)\n for i in 0:(2d-1)\n if i > 0\n companion[i + 1, i] = 1.0\n end\n companion[i + 1, end] = -MP.coefficient(p, x^i)\n end\n F = LinearAlgebra.schur(complex(companion))\n q = one(p)\n i = 1\n while i <= length(F.values)\n root = F.values[i]\n q *= (x - root)\n if !isapprox(real(root), real(F.values[i+1]), rtol=tol, atol=tol)\n return # Cannot happen for complex conjugate root so it means that we have a root which does not have an even multiplicity This means that the polynomial is not nonnegative\n end\n i += 2\n end\n q1 = MP.map_coefficients(real, q)\n q2 = MP.map_coefficients(imag, q)\n return SOS.SOSDecomposition([q1, q2])\nend\n\nmutable struct Optimizer <: MOI.AbstractOptimizer\n p::Union{Nothing,MP.AbstractPolynomial}\n decomposition::Union{Nothing,SOS.SOSDecomposition}\n tol::Float64\n function Optimizer()\n return new(nothing, nothing, 1e-6)\n end\nend\n\nMOI.is_empty(optimizer::Optimizer) = optimizer.p === nothing\nfunction MOI.empty!(optimizer::Optimizer)\n optimizer.p = nothing\n return\nend\n\nfunction MOI.supports_constraint(::Optimizer, ::Type{<:MOI.VectorAffineFunction}, ::Type{<:SOS.SOSPolynomialSet{SOS.FullSpace}})\n return true\nend\nfunction MOI.add_constraint(optimizer::Optimizer, func::MOI.VectorAffineFunction, set::SOS.SOSPolynomialSet{SOS.FullSpace})\n if optimizer.p !== nothing\n error(\"Only one constraint is supported\")\n end\n if !isempty(func.terms)\n error(\"Only supports constant polynomials\")\n end\n optimizer.p = MP.polynomial(func.constants, set.monomials)\n return MOI.ConstraintIndex{typeof(func),typeof(set)}(1) # There will be only ever one constraint so the index does not matter.\nend\n\nMOI.supports_incremental_interface(::Optimizer) = true\nfunction MOI.copy_to(optimizer::Optimizer, model::MOI.ModelLike)\n return MOI.Utilities.default_copy_to(optimizer, model)\nend\nfunction MOI.optimize!(optimizer::Optimizer)\n optimizer.decomposition = decompose(optimizer.p, optimizer.tol)\nend\n\nfunction MOI.get(optimizer::Optimizer, ::MOI.TerminationStatus)\n if optimizer.decomposition === nothing\n return MOI.INFEASIBLE\n else\n return MOI.OPTIMAL\n end\nend\n\nfunction MOI.get(optimizer::Optimizer, ::MOI.PrimalStatus)\n if optimizer.decomposition === nothing\n return MOI.NO_SOLUTION\n else\n return MOI.FEASIBLE_POINT\n end\nend\n\nfunction MOI.get(optimizer::Optimizer, ::SOS.SOSDecompositionAttribute, ::MOI.ConstraintIndex)\n return optimizer.decomposition\nend\n\nend","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"We define the same function both for our new solver and SDP solvers.","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"using SumOfSquares\nfunction decompose(p, solver)\n model = Model(solver)\n con = @constraint(model, p in SOSCone())\n optimize!(model)\n @assert primal_status(model) == MOI.FEASIBLE_POINT\n return sos_decomposition(con)\nend","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"We consider the following univariate polynomial from Example 3.35 of [BPT12].","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"Using our solver we find the following decomposition in two squares.","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"using DynamicPolynomials\n@polyvar x\np = x^4 + 4x^3 + 6x^2 + 4x + 5\ndec = decompose(p, MyUnivariateSolver.Optimizer)","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"We can verify as follows that it gives a correct decomposition:","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"polynomial(dec)","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"We can also use a semidefinite solver:","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"import CSDP\ndec = decompose(p, CSDP.Optimizer)","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"The decomposition is different, it is the sum of 3 squares. However, it is also valid:","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"polynomial(dec)","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"","category":"page"},{"location":"generated/Extension/univariate_solver/","page":"Univariate Solver","title":"Univariate Solver","text":"This page was generated using Literate.jl.","category":"page"}] +} diff --git a/previews/PR347/siteinfo.js b/previews/PR347/siteinfo.js new file mode 100644 index 000000000..f44d6784e --- /dev/null +++ b/previews/PR347/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "previews/PR347"; diff --git a/previews/PR347/sumofsquares/index.html b/previews/PR347/sumofsquares/index.html new file mode 100644 index 000000000..a807af574 --- /dev/null +++ b/previews/PR347/sumofsquares/index.html @@ -0,0 +1,2 @@ + +Sum-of-Squares Programming · SumOfSquares

Sum-of-Squares Programming

This section contains a brief introduction to Sum-of-Squares Programming. For more details, see [BPT12, Las09, Lau09].

Quadratic forms and Semidefinite programming

The positive semidefiniteness of a $n \times n$ real symmetric matrix $Q$ is equivalent to the nonnegativity of the quadratic form $p(x) = x^\top Q x$ for all vector $x \in \mathbb{R}^n$. For instance, the polynomial

\[x_1^2 + 2x_1x_2 + 5x_2^2 + 4x_2x_3 + x_3^2 = x^\top \begin{pmatrix}1 & 1 & 0\\1 & 5 & 2\\ 0 & 2 & 1\end{pmatrix} x\]

is nonnegative since the matrix of the right-hand side is positive semidefinite. Moreover, a certificate of nonnegativity can be extracted from the Cholesky decomposition of the matrix:

\[(x_1 + x_2)^2 + (2x_2 + x_3)^2 = x^\top \begin{pmatrix}1 & 1 & 0\\0 & 2 & 1\end{pmatrix}^\top \begin{pmatrix}1 & 1 & 0\\0 & 2 & 1\end{pmatrix} x\]

Polynomial nonnegativity and Semidefinite programming

This can be generalized to a polynomial of arbitrary degree. A polynomial $p(x)$ is nonnegative if it can be rewritten as $p(x) = X^\top Q X$ where $Q$ is a real symmetric positive semidefinite matrix and $X$ is a vector of monomials.

For instance

\[x_1^2 + 2x_1^2x_2 + 5x_1^2x_2^2 + 4x_1x_2^2 + x_2^2 = X^\top \begin{pmatrix}1 & 1 & 0\\1 & 5 & 2\\ 0 & 2 & 1\end{pmatrix} X\]

where $X = (x_1, x_1x_2, x_2)$ Similarly to the previous section, the Cholesky factorization of the matrix can be used to extract a sum of squares certificate of nonnegativity for the polynomial:

\[(x_1 + x_1x_2)^2 + (2x_1x_2 + x_2)^2 = X^\top \begin{pmatrix}1 & 1 & 0\\0 & 2 & 1\end{pmatrix}^\top \begin{pmatrix}1 & 1 & 0\\0 & 2 & 1\end{pmatrix} X\]

When is nonnegativity equivalent to sum of squares ?

Determining whether a polynomial is nonnegative is NP-hard. The condition of the previous section was only sufficient, that is, there exists nonnegative polynomials that are not sums of squares. Hilbert showed in 1888 that there are exactly 3 cases for which there is equivalence between the nonnegativity of the polynomials of $n$ variables and degree $2d$ and the existence of a sum of squares decomposition.

  • $n = 1$ : Univariate polynomials
  • $2d = 2$ : Quadratic polynomials
  • $n = 2$, $2d = 4$ : Bivariate quartics

The first explicit example of polynomial that was not a sum of squares was given by Motzkin in 1967:

\[x_1^4x_2^2 + x_1^2x_2^4 + 1 - 3x_1^2x_2^2 \geq 0 \quad \forall x\]

While it is not a sum of squares, it can still be certified to be nonnegative using sum-of-squares programming by identifying it with a rational sum-of-squares decomposition. These facts can be verified numerically using this package as detailed in the Motzkin example.

References

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

[Lau09] Laurent, M. Sums of squares, moment matrices and optimization over polynomials Emerging applications of algebraic geometry, Springer, 2009, 157-270.

diff --git a/previews/PR347/tutorials/Extension/certificate.jl b/previews/PR347/tutorials/Extension/certificate.jl new file mode 100644 index 000000000..1009dee95 --- /dev/null +++ b/previews/PR347/tutorials/Extension/certificate.jl @@ -0,0 +1,108 @@ +# # Certificate + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Extension/certificate.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Extension/certificate.ipynb) +# **Contributed by**: Benoît Legat + +# ## Introduction + +# Consider the polynomial optimization problem (a variation from [Lasserre2009; Example 2.2](@cite)) of +# minimizing the polynomial $x^3 - x^2 + 2xy - y^2 + y^3$ +# over the polyhedron defined by the inequalities $x \ge 0, y \ge 0$ and $x + y \geq 1$. + +using Test #src +using DynamicPolynomials +@polyvar x y +p = x^3 - x^2 + 2x*y - y^2 + y^3 + x^3 * y +using SumOfSquares +S = @set x >= 0 && y >= 0 && x^2 + y^2 >= 2 + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# Note that SumOfSquares generates a *standard form* SDP (i.e., SDP variables +# and equality constraints) while SCS expects a *geometric form* SDP (i.e., +# free variables and symmetric matrices depending affinely on these variables +# constrained to belong to the PSD cone). +# JuMP will transform the standard from to the geometric form will create the PSD +# variables as free variables and then constrain then to be PSD. +# While this will work, since the dual of a standard from is in in geometric form, +# dualizing the problem will generate a smaller SDP. +# We use therefore `Dualization.dual_optimizer` so that SCS solves the dual problem. + +import SCS +using Dualization +solver = dual_optimizer(SCS.Optimizer) + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following program searches for the largest lower bound. + +model = SOSModel(solver) +@variable(model, α) +@objective(model, Max, α) +@constraint(model, c, p >= α, domain = S) +optimize!(model) + +# We can see that the problem is infeasible, meaning that no lower bound was found. + +@test termination_status(model) == MOI.INFEASIBLE #src +@test dual_status(model) == MOI.INFEASIBILITY_CERTIFICATE #src +solution_summary(model) + +# We now define the Schmüdgen's certificate: + +import MultivariateBases as MB +const SOS = SumOfSquares +const SOSC = SOS.Certificate +struct Schmüdgen{IC <: SOSC.AbstractIdealCertificate, CT <: SOS.SOSLikeCone, BT <: SOS.AbstractPolynomialBasis} <: SOSC.AbstractPreorderCertificate + ideal_certificate::IC + cone::CT + basis::Type{BT} + maxdegree::Int +end + +SOSC.cone(certificate::Schmüdgen) = certificate.cone + +function SOSC.preprocessed_domain(::Schmüdgen, domain::BasicSemialgebraicSet, p) + return SOSC.with_variables(domain, p) +end + +function SOSC.preorder_indices(::Schmüdgen, domain::SOSC.WithVariables) + n = length(domain.inner.p) + if n >= Sys.WORD_SIZE + error("There are $(2^n - 1) products in Schmüdgen's certificate, they cannot even be indexed with `$Int`.") + end + return map(SOSC.PreorderIndex, 1:(2^n-1)) +end + +function SOSC.multiplier_basis(certificate::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables) + q = SOSC.generator(certificate, index, domain) + return SOSC.maxdegree_gram_basis(certificate.basis, variables(domain), SOSC.multiplier_maxdegree(certificate.maxdegree, q)) +end +function SOSC.multiplier_basis_type(::Type{Schmüdgen{IC, CT, BT}}) where {IC, CT, BT} + return BT +end + +function SOSC.generator(::Schmüdgen, index::SOSC.PreorderIndex, domain::SOSC.WithVariables) + I = [i for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))] + return prod([domain.inner.p[i] for i in eachindex(domain.inner.p) if !iszero(index.value & (1 << (i - 1)))]) +end + +SOSC.ideal_certificate(certificate::Schmüdgen) = certificate.ideal_certificate +SOSC.ideal_certificate(::Type{<:Schmüdgen{IC}}) where {IC} = IC + +SOS.matrix_cone_type(::Type{<:Schmüdgen{IC, CT}}) where {IC, CT} = SOS.matrix_cone_type(CT) + +# Let's try again with our the Schmüdgen certificate: + +model = SOSModel(solver) +@variable(model, α) +@objective(model, Max, α) +ideal_certificate = SOSC.Newton(SOSCone(), MB.MonomialBasis, tuple()) +certificate = Schmüdgen(ideal_certificate, SOSCone(), MB.MonomialBasis, maxdegree(p)) +@constraint(model, c, p >= α, domain = S, certificate = certificate) +optimize!(model) +@test termination_status(model) == MOI.OPTIMAL #src +@test primal_status(model) == MOI.FEASIBLE_POINT #src +@test objective_value(model) ≈ 0.8284 rtol=1e-3 #src +@test length(lagrangian_multipliers(c)) == 7 #src +solution_summary(model) diff --git a/previews/PR347/tutorials/Extension/hypercube.jl b/previews/PR347/tutorials/Extension/hypercube.jl new file mode 100644 index 000000000..d67304eab --- /dev/null +++ b/previews/PR347/tutorials/Extension/hypercube.jl @@ -0,0 +1,114 @@ +# # Hypercube + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Extension/hypercube.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Extension/hypercube.ipynb) +# **Contributed by**: Benoît Legat + +# Given a Sum-of-Squares constraint on an algebraic set: +# ```math +# g_1(x) = , \ldots, g_m(x) = 0 \Rightarrow p(x) \ge 0. +# ``` +# We can either use the certificate: +# ```math +# p(x) = s(x) + \lambda_1(x) g_1(x) + \cdots + \lambda_m(x) g_m(x), s_0(x) \text{ is SOS}, +# ``` +# or +# ```math +# p(x) \equiv s(x) \pmod{\la g_1(x), \ldots, g_m(x) \ra}, s_0(x) \text{ is SOS}. +# ``` +# the second one leads to a *simpler* SDP but needs to compute a *Gr\"obner* basis: +# * SemialgebraicSets implements Buchberger's algorithm. +# * The `@set` macro recognizes variable fix, e.g., `x = 1` +# and provides shortcut. +# * If you know a \alert{better} way to take modulo, +# better create your \alert{own} type of algebraic set! + +# We illustrate this in this example. + +using DynamicPolynomials +@polyvar x[1:3] +p = sum(x)^2 +using SumOfSquares +S = algebraicset([xi^2 - 1 for xi in x]) + +# We will now search for the minimum of `x` over `S` using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + +function min_algebraic(S) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = S) + optimize!(model) + @show termination_status(model) + @show objective_value(model) +end + +min_algebraic(S) + +# Note that the minimum is in fact `1`. +# Indeed, since each variables is odd (it is either `-1` or `1`) +# and there is an odd number of variables, their sum is odd. +# Therefore it cannot be zero! + +# We can see that the Gröbner basis of `S` was computed + +@show S.I.gröbner_basis +S.I.algo + +# The Gröbner basis is simple to compute in this case as the vector +# of `xi^2 - 1` is already a Gröbner basis. +# However, we still need to divide polynomials by the Gröbner basis +# which can be simplified in this case. + +const MP = MultivariatePolynomials +const SS = SemialgebraicSets +struct HypercubeIdeal{V} <: SS.AbstractPolynomialIdeal + variables::Vector{V} +end +struct HypercubeSet{V} <: SS.AbstractAlgebraicSet + ideal::HypercubeIdeal{V} +end +MP.variables(set::HypercubeSet) = MP.variables(set.ideal) +MP.variables(ideal::HypercubeIdeal) = ideal.variables +Base.similar(set::HypercubeSet, ::Type) = set +SS.ideal(set::HypercubeSet) = set.ideal +function Base.rem(p, set::HypercubeIdeal) + return MP.polynomial(map(MP.terms(p)) do term + mono = MP.monomial(term) + new_mono = one(mono) + for (var, exp) in powers(mono) + if var in set.variables + exp = rem(exp, 2) + end + new_mono *= var^exp + end + MP.coefficient(term) * new_mono + end) +end + +H = HypercubeSet(HypercubeIdeal(x)) + +min_algebraic(H) + +# Let's now try to find the correct lower bound: + +function min_algebraic_rational(S, d) + model = SOSModel(solver) + @variable(model, q, SOSPoly(MP.monomials(x, 0:d))) + deno = q + 1 + @constraint(model, c, deno * p >= deno, domain = S) + optimize!(model) + @show termination_status(model) +end + +# With `d = 0`, it's the same as previously + +min_algebraic_rational(H, 0) + +# But with `d = 1`, we can find the correct lower bound + +min_algebraic_rational(H, 1) diff --git a/previews/PR347/tutorials/Extension/typed.jl b/previews/PR347/tutorials/Extension/typed.jl new file mode 100644 index 000000000..5339a351a --- /dev/null +++ b/previews/PR347/tutorials/Extension/typed.jl @@ -0,0 +1,104 @@ +# # Multivariate polynomials implementations + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Extension/typed.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Extension/typed.ipynb) +# **Contributed by**: Benoît Legat + +# The SumOfSquares package is built on top of the [MultivariatePolynomials](https://github.com/JuliaAlgebra/MultivariatePolynomials.jl) +# abstract interface. [DynamicPolynomials](https://github.com/JuliaAlgebra/DynamicPolynomials.jl/) +# is an implementation of this abstract interface so it can be used with +# SumOfSquares. Moreover, any other implementation can be used as well. To +# illustrate, we solve Examples 3.38 of [BPT12] with +# [TypedPolynomials](https://github.com/JuliaAlgebra/TypedPolynomials.jl), +# another implementation of [MultivariatePolynomials](https://github.com/JuliaAlgebra/MultivariatePolynomials.jl). +# +# [BPT12] Blekherman, G. & Parrilo, P. A. & Thomas, R. R. +# *Semidefinite Optimization and Convex Algebraic Geometry*. +# Society for Industrial and Applied Mathematics, **2012**. + +using Test #src +import TypedPolynomials +TypedPolynomials.@polyvar x y +using SumOfSquares +import CSDP +model = SOSModel(CSDP.Optimizer) +con_ref = @constraint(model, 2x^4 + 5y^4 - x^2*y^2 >= -2(x^3*y + x + 1)) +optimize!(model) +solution_summary(model) + +# We see that the problem is feasible. The Sum-of-Squares decomposition can be +# obtained as follows: + +sos_decomposition(con_ref) + +# Why is there several implementations ? +# Depending in the use-case, one implementation may be more appropriate than +# another one. [TypedPolynomials](https://github.com/JuliaAlgebra/TypedPolynomials.jl) +# is faster than [DynamicPolynomials](https://github.com/JuliaAlgebra/DynamicPolynomials.jl/) +# but it requires new compilation whenever the list of variables changes. +# This means that [TypedPolynomials](https://github.com/JuliaAlgebra/TypedPolynomials.jl) +# is not appropriate when the number of variables is dynamic or too large. +# However, for a small number of variables, it can be faster. +# When solving Sum-of-Squares programs, the time is mostly taken by the Semidefinite programming solver. +# The time taken by SumOfSquares/JuMP/MathOptInterface are usually negligible +# or it time is taken by manipulation of JuMP or MathOptInterface functions +# therefore using TypedPolynomials over DynamicPolynomials may not make much difference in most cases. + +# One case for which using TypedPolynomials might be adequate is when +# using domain defined by equalities (possibly also with inequalities). +# Indeed, in that case, SumOfSquares computes the corresponding Gröbner basis which +# may take a non-negligible amount of time for large systems of equalities. + +# To illustrate this, consider the computation of Gröbner basis for the +# following system from [CLO05, p. 17]. +# The time taken by TypedPolynomials is below: +# +# [CLO05] Cox, A. David & Little, John & O'Shea, Donal +# *Using Algebraic Geometry*. +# Graduate Texts in Mathematics, **2005**. +# https://doi.org/10.1007/b138611 + +using BenchmarkTools +@btime let + TypedPolynomials.@polyvar x y + S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y + SemialgebraicSets.compute_gröbner_basis!(S.I) +end + +# The time taken by DynamicPolynomials is as follows: + +import DynamicPolynomials +@btime let + DynamicPolynomials.@polyvar x y + S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y + SemialgebraicSets.compute_gröbner_basis!(S.I) +end + +# We see that TypedPolynomials is faster. +# The time is still negligible for this small system but for larger systems, choosing TypedPolynomials may be helpful. +# We can use this system in a Sum-of-Squares constraint as follows: + +TypedPolynomials.@polyvar x y +S = @set x^3 * y + x == 2x^2 * y^2 && 3x^4 == y +poly = -6x - 4y^3 + 2x*y^2 + 6x^3 - 3y^4 + 13x^2 * y^2 +model = Model(CSDP.Optimizer) +con_ref = @constraint(model, poly in SOSCone(), domain = S) +optimize!(model) +solution_summary(model) + +# We obtain the following decomposition: + +dec = sos_decomposition(con_ref, 1e-6) + +# We can verify that it is correct as follows: + +# TODO remove `polynomial` #src +@test SumOfSquares.MP.isapproxzero(rem(dec - poly, S.I), ztol = 1e-4) #src +rem(dec - poly, S.I) + +# Note that the difference between `dec` and `poly` is larger +# than between the full gram matrix because `dec` is obtained by dropping +# the lowest eigenvalues with the threshold `1e-6`; see [`sos_decomposition`](@ref). + +@test SumOfSquares.MP.isapproxzero(rem(gram_matrix(con_ref) - poly, S.I), ztol = 1e-6) #src +rem(gram_matrix(con_ref) - poly, S.I) diff --git a/previews/PR347/tutorials/Extension/univariate_solver.jl b/previews/PR347/tutorials/Extension/univariate_solver.jl new file mode 100644 index 000000000..b8e065164 --- /dev/null +++ b/previews/PR347/tutorials/Extension/univariate_solver.jl @@ -0,0 +1,161 @@ +# # Univariate Solver + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Extension/univariate_solver.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Extension/univariate_solver.ipynb) +# **Contributed by**: Benoît Legat + +# When using an SDP solver, the Sum-of-Squares constraint is bridged +# into a semidefinite constraint. This reformulation is done only if the +# solver does not support the Sum-of-Squares constraint. We show in this tutorial how to define a solver that supports such constraint. +# The *same* model with be then solved with or without reformulation depending on the solver. + +# We consider a solver that would support finding the SOS decomposition +# of nonnegative univariate polynomials. + +using Test #src + +module MyUnivariateSolver + +import LinearAlgebra +import MathOptInterface as MOI +import MultivariatePolynomials as MP +import SumOfSquares as SOS + +function decompose(p::MP.AbstractPolynomial, tol=1e-6) + vars = MP.effective_variables(p) + if length(vars) != 1 + error("$p is not univariate") + end + x = first(vars) + lead = MP.leading_coefficient(p) + if !isone(lead) + p = p / lead + end + deg = MP.maxdegree(p) + if isodd(deg) + return + end + d = div(deg, 2) + companion = zeros(2d, 2d) + for i in 0:(2d-1) + if i > 0 + companion[i + 1, i] = 1.0 + end + companion[i + 1, end] = -MP.coefficient(p, x^i) + end + F = LinearAlgebra.schur(complex(companion)) + q = one(p) + i = 1 + while i <= length(F.values) + root = F.values[i] + q *= (x - root) + if !isapprox(real(root), real(F.values[i+1]), rtol=tol, atol=tol) + return # Cannot happen for complex conjugate root so it means that we have a root which does not have an even multiplicity This means that the polynomial is not nonnegative + end + i += 2 + end + q1 = MP.map_coefficients(real, q) + q2 = MP.map_coefficients(imag, q) + return SOS.SOSDecomposition([q1, q2]) +end + +mutable struct Optimizer <: MOI.AbstractOptimizer + p::Union{Nothing,MP.AbstractPolynomial} + decomposition::Union{Nothing,SOS.SOSDecomposition} + tol::Float64 + function Optimizer() + return new(nothing, nothing, 1e-6) + end +end + +MOI.is_empty(optimizer::Optimizer) = optimizer.p === nothing +function MOI.empty!(optimizer::Optimizer) + optimizer.p = nothing + return +end + +function MOI.supports_constraint(::Optimizer, ::Type{<:MOI.VectorAffineFunction}, ::Type{<:SOS.SOSPolynomialSet{SOS.FullSpace}}) + return true +end +function MOI.add_constraint(optimizer::Optimizer, func::MOI.VectorAffineFunction, set::SOS.SOSPolynomialSet{SOS.FullSpace}) + if optimizer.p !== nothing + error("Only one constraint is supported") + end + if !isempty(func.terms) + error("Only supports constant polynomials") + end + optimizer.p = MP.polynomial(func.constants, set.monomials) + return MOI.ConstraintIndex{typeof(func),typeof(set)}(1) # There will be only ever one constraint so the index does not matter. +end + +MOI.supports_incremental_interface(::Optimizer) = true +function MOI.copy_to(optimizer::Optimizer, model::MOI.ModelLike) + return MOI.Utilities.default_copy_to(optimizer, model) +end +function MOI.optimize!(optimizer::Optimizer) + optimizer.decomposition = decompose(optimizer.p, optimizer.tol) +end + +function MOI.get(optimizer::Optimizer, ::MOI.TerminationStatus) + if optimizer.decomposition === nothing + return MOI.INFEASIBLE + else + return MOI.OPTIMAL + end +end + +function MOI.get(optimizer::Optimizer, ::MOI.PrimalStatus) + if optimizer.decomposition === nothing + return MOI.NO_SOLUTION + else + return MOI.FEASIBLE_POINT + end +end + +function MOI.get(optimizer::Optimizer, ::SOS.SOSDecompositionAttribute, ::MOI.ConstraintIndex) + return optimizer.decomposition +end + +end + +# We define the same function both for our new solver and SDP solvers. + +using SumOfSquares +function decompose(p, solver) + model = Model(solver) + con = @constraint(model, p in SOSCone()) + optimize!(model) + @assert primal_status(model) == MOI.FEASIBLE_POINT + return sos_decomposition(con) +end + +# We consider the following univariate polynomial from +# Example 3.35 of [BPT12]. +# +# [BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. +# *Semidefinite Optimization and Convex Algebraic Geometry*. +# Society for Industrial and Applied Mathematics, **2012**. + +# Using our solver we find the following decomposition in two squares. + +using DynamicPolynomials +@polyvar x +p = x^4 + 4x^3 + 6x^2 + 4x + 5 +dec = decompose(p, MyUnivariateSolver.Optimizer) + +# We can verify as follows that it gives a correct decomposition: + +@test polynomial(dec) ≈ p #src +polynomial(dec) + +# We can also use a semidefinite solver: + +import CSDP +dec = decompose(p, CSDP.Optimizer) +@test length(dec.ps) == 3 #src +@test polynomial(dec) ≈ p #src + +# The decomposition is different, it is the sum of 3 squares. +# However, it is also valid: + +polynomial(dec) diff --git a/previews/PR347/tutorials/Getting started/circle.jl b/previews/PR347/tutorials/Getting started/circle.jl new file mode 100644 index 000000000..fdc1e26a9 --- /dev/null +++ b/previews/PR347/tutorials/Getting started/circle.jl @@ -0,0 +1,39 @@ +# # Nonnegative over a variety + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/circle.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/circle.ipynb) + +# The polynomial ``1 - y^2`` is nonnegative for all ``y`` in the unit circle. +# This can be verified using Sum-of-Squares. + +using Test #src +using DynamicPolynomials +using SumOfSquares +@polyvar x y +S = @set x^2 + y^2 == 1 + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# The domain over which the nonnegativity of ``1 - y^2`` should be certified +# is specified through the `domain` keyword argument. + +import CSDP +model = SOSModel(CSDP.Optimizer) +set_silent(model) +con_ref = @constraint(model, 1 - y^2 >= 0, domain = S) +optimize!(model) + +# We can see that the model was feasible: + +@test JuMP.termination_status(model) == MOI.OPTIMAL #src +@test JuMP.primal_status(model) == MOI.FEASIBLE_POINT #src +solution_summary(model) + +# The certificate can be obtained as follows: + +dec = sos_decomposition(con_ref, 1e-6) #src +@test length(dec) == 1 #src +@test first(dec) ≈ x rtol = 1e-6 #src +sos_decomposition(con_ref, 1e-6) + +# It returns ``x^2`` which is a valid certificate as: +# $$ 1 - y^2 \equiv x^2 \pmod{x^2 + y^2 - 1} $$ diff --git a/previews/PR347/tutorials/Getting started/dualization.jl b/previews/PR347/tutorials/Getting started/dualization.jl new file mode 100644 index 000000000..554a54605 --- /dev/null +++ b/previews/PR347/tutorials/Getting started/dualization.jl @@ -0,0 +1,144 @@ +# # On the importance of Dualization + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/dualization.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/dualization.ipynb) + +using Test #src +using DynamicPolynomials +using SumOfSquares + +# Sum-of-Squares programs are usually solved by SemiDefinite Programming solvers (SDPs). +# These programs can be represented into two different formats: +# Either the *standard conic form*, also known as *kernel form*: +# ```math +# \begin{aligned} +# \min\limits_{Q \in \mathbb{S}_n} & \langle C, Q \rangle\\ +# \text{subject to:} & \langle A_i, Q \rangle = b_i, \quad i=1,2,\ldots,m\\ +# & Q \succeq 0, +# \end{aligned} +# ``` +# or the *geometric conic form*, also known as *image form*: +# ```math +# \begin{aligned} +# \max\limits_{y \in \mathbb{R}^m} & \langle b, y \rangle\\ +# \text{subject to:} & C \succeq \sum_{i=1}^m A_i y_i\\ +# & y\ \mathsf{free}, +# \end{aligned} +# ``` + +# In this tutorial, we investigate in which of these two forms a Sum-of-Squares +# constraint should be written into. +# Consider the simple example of trying to determine whether the following univariate +# polynomial is a Sum-of-Squares: + +import SCS +@polyvar x +p = (x + 1)^2 * (x + 2)^2 +model_scs = Model(SCS.Optimizer) +con_ref = @constraint(model_scs, p in SOSCone()) +optimize!(model_scs) + +# As we can see in the log, SCS reports `6` variables and `11` constraints. +# We can also choose to dualize the problem before it is +# passed to SCS as follows: + +using Dualization +model_dual_scs = Model(dual_optimizer(SCS.Optimizer)) +@objective(model_dual_scs, Max, 0.0) +con_ref = @constraint(model_dual_scs, p in SOSCone()) +optimize!(model_dual_scs) + +# This time, SCS reports `5` variables and `6` constraints. + +# ## Bridges operating behind the scenes +# +# The difference comes from the fact that, when designing the JuMP interface of +# SCS, it was decided that the model would be read in the image form. +# SCS therefore declares that it only supports free variables, represented in +# JuMP as variables in `MOI.Reals` and affine semidefinite constraints, +# represented in JuMP as +# `MOI.VectorAffineFunction`-in-`MOI.PositiveSemidefiniteConeTriangle` +# constraints. +# On the other hand, SumOfSquares gave the model in kernel form so the +# positive semidefinite (PSD) variables were reformulated as free variables +# constrained to be PSD using an affine PSD constraints. +# +# This transformation is done transparently without warning but it can be +# inspected using `print_active_bridges`. +# As shown below, we can see +# `Unsupported variable: MOI.PositiveSemidefiniteConeTriangle` and +# `adding as constraint` +# indicating that PSD variables are not supported and they are added as free +# variables. +# Then we have `Unsupported constraint: MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle` +# indicating that SCS does not support constraining variables in the PSD cone +# so it will just convert it into affine expressions in the PSD cone. +# Of course, this is equivalent but it means that SCS will not exploit this +# particular structure of the problem hence solving might be less efficient. + +print_active_bridges(model_scs) + +# With the dual version, we can see that variables in the PSD cone are supported +# directly hence we don't need that extra conversion. + +print_active_bridges(model_dual_scs) + +# ## In more details +# +# Consider a polynomial +# ```math +# p(x) = \sum_{\alpha} p_\alpha x^\alpha, +# ``` +# a vector of monomials `b(x)` and the set +# ```math +# \mathcal{A}_\alpha = \{\,(\beta, \gamma) \in b(x)^2 \mid x^\beta x^\gamma = x^\alpha\,\} +# ``` +# The constraint encoding the existence of a PSD matrix `Q` such that `p(x) = b(x)' * Q * b(x)` +# can be written in standard conic form as follows: +# ```math +# \begin{aligned} +# \langle \sum_{(\beta, \gamma) \in \mathcal{A}_\alpha} e_\beta e_\gamma^\top, Q \rangle & = p_\alpha, \quad\forall \alpha\\ +# Q & \succeq 0 +# \end{aligned} +# ``` +# Given an arbitrary choice of elements in each set ``\mathcal{A}_\alpha``: +# ``(\beta_\alpha, \gamma_\alpha) \in \mathcal{A}_\alpha``. +# It can also equivalently be written in the geometric conic form as follows: +# ```math +# \begin{aligned} +# p_\alpha e_{\beta_\alpha} e_{\gamma_\alpha}^\top + +# \sum_{(\beta, \gamma) \in \mathcal{A}_\alpha \setminus (\beta_\alpha, \gamma_\alpha)} +# y_{\beta,\gamma} (e_\beta e_\gamma - e_{\beta_\alpha} e_{\gamma_\alpha}^\top)^\top +# & \succeq 0\\ +# y_{\beta,\gamma} & \text{ free} +# \end{aligned} +# ``` +# +# ## Should I dualize or not ? +# +# Let's study the evolution of the dimensions `m` and `n` of the semidefinite +# program in two extreme examples and then try to extrapolate from these. +# +# ### Univariate case +# +# Suppose `p` is a univariate polynomial of degree $2d$. +# Then `n` will be equal to `d(d + 1)/2` for both the standard and geometric conic forms. +# On the other hand, `m` will be equal to `2d + 1` for the standard conic form and +# `d(d + 1) / 2 - (2d + 1)` for the geometric form case. +# So `m` grows **linearly** for the kernel form but **quadratically** for the image form! +# +# ### Quadratic case +# +# Suppose `p` is a quadratic form of `d` variables. +# Then `n` will be equal to `d` for both the standard and geometric conic forms. +# On the other hand, `m` will be equal to `d(d + 1)/2` for the standard conic form and +# `0` for the geometric form case. +# So `m` grows **quadratically** for the kernel form but is zero for the image form! +# +# ### In general +# +# In general, if ``s_d`` is the dimension of the space of polynomials of degree `d` then +# ``m = s_{2d}`` for the kernel form and ``m = s_{d}(s_{d} + 1)/2 - s_{2d}`` for the image form. +# As a rule of thumb, the kernel form will have a smaller `m` if `p` has a low number of variables +# and low degree and vice versa. +# Of course, you can always try with and without Dualization and see which one works best. diff --git a/previews/PR347/tutorials/Getting started/getting_started.jl b/previews/PR347/tutorials/Getting started/getting_started.jl new file mode 100644 index 000000000..ad4b6de17 --- /dev/null +++ b/previews/PR347/tutorials/Getting started/getting_started.jl @@ -0,0 +1,63 @@ +# # Getting started + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/getting_started.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/getting_started.ipynb) +# **Adapted from**: SOSTOOLS' SOSDEMO1 (See Section 4.1 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf)) and Example 2.4 of [PJ08] +# +# P. Parrilo and A. Jadbabaie +# *Approximation of the joint spectral radius using sum of squares*. +# Linear Algebra and its Applications, Elsevier (2008), 428, 2385-2402 + +using Test #src +using DynamicPolynomials +@polyvar x y +p = 2*x^4 + 2*x^3*y - x^2*y^2 + 5*y^4 + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints. + +using SumOfSquares +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver) +con_ref = @constraint(model, p >= 0) +optimize!(model) +@test primal_status(model) == MOI.FEASIBLE_POINT #src +primal_status(model) + +# We see above that the solver found a feasible solution. +# We now inspect this solution: + +q = gram_matrix(con_ref) +Q = value_matrix(q) #src +@test isapprox(Q[1, 1], 5, rtol=1e-5) #src +@test isapprox(Q[3, 2], 1, rtol=1e-5) #src +@test isapprox(Q[3, 3], 2, rtol=1e-5) #src +@test abs(Q[2, 1]) < 1e-5 #src +@test isapprox(Q[2, 2] + 2Q[1, 3], -1, rtol=1e-5) #src + +# We can get the SOS decomposition from the gram matrix as follows: + +sosdec = SOSDecomposition(q) +@test isapprox(sosdec, sos_decomposition(con_ref)) #src +@test isapprox(sum(sosdec.ps.^2), p; rtol=1e-4, ztol=1e-6) #src + +# We now seek for the SOS decomposition of the following polynomial: + +p = 4*x^4*y^6 + x^2 - x*y^2 + y^2 + +# We build the same model as previously with this new polynomial. +# Here we can use `Model` instead of `SOSModel` as we explicitly constrain +# `p` to belong to the SOS cone with `p in SOSCone()`. + +model = Model(solver) +con_ref = @constraint(model, p in SOSCone()) +optimize!(model) +@test primal_status(model) == MOI.FEASIBLE_POINT #src +primal_status(model) + +# We can query the SOS decomposition directly from the constraint reference +# as follows: + +sos_decomposition(con_ref) +# p should be GramMatrix([1, 0, -1/2, 0, -1, 1, 0, -2/3, 0, 4/3, 0, 0, 2, 0, 4], [y, x, x*y, x*y^2, x^2*y^3]) #src diff --git a/previews/PR347/tutorials/Getting started/motzkin.jl b/previews/PR347/tutorials/Getting started/motzkin.jl new file mode 100644 index 000000000..c87733d10 --- /dev/null +++ b/previews/PR347/tutorials/Getting started/motzkin.jl @@ -0,0 +1,109 @@ +# # Motzkin + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/motzkin.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/motzkin.ipynb) +# **Adapted from**: (3.6) and (3.19) of [BPT12] +# +# [BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. +# *Semidefinite Optimization and Convex Algebraic Geometry*. +# Society for Industrial and Applied Mathematics, **2012**. + +# The first explicit example of nonnegative polynomial that is not a sum of squares was found by Motzkin in 1967. By the [Arithmetic-geometric mean](https://en.wikipedia.org/wiki/Arithmetic%E2%80%93geometric_mean), +# $$ \frac{x^4y^2 + x^2y^4 + 1}{3} \ge \sqrt[3]{x^4y^2 \cdot x^2y^4 \cdot 1} = x^2y^2 $$ +# hence +# $$ x^4y^2 + x^2y^4 + 1 - 3x^2y^2 \ge 0. $$ +# The code belows construct the Motzkin polynomial using [DynamicPolynomials](https://github.com/JuliaAlgebra/DynamicPolynomials.jl). + +using Test #src +using DynamicPolynomials +@polyvar x y +motzkin = x^4*y^2 + x^2*y^4 + 1 - 3x^2*y^2 + +# The Motzkin polynomial is nonnegative but is not a sum of squares as we can verify numerically as follows. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +using SumOfSquares +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver) +@constraint(model, motzkin >= 0) # We constraint `motzkin` to be a sum of squares + +optimize!(model) + +# We see that the problem is detected as infeasible... + +@test termination_status(model) == MOI.INFEASIBLE #src +termination_status(model) + +# ... and that the dual solution is a certificate of the infeasibility of the problem. + +@test dual_status(model) == MOI.INFEASIBILITY_CERTIFICATE #src +dual_status(model) + +# Even if the Motzkin polynomial is not a sum of squares, it can still be certified to be nonnegative using sums of squares. +# Indeed a polynomial is certified to be nonnegative if it is equal to a fraction of sums of squares. +# The Motzkin polynomial is equal to a fraction of sums of squares whose denominator is $x^2 + y^2$. +# This can be verified numerically as follows: + +model = SOSModel(solver) +@constraint(model, (x^2 + y^2) * motzkin >= 0) # We constraint the `(x^2 + y^2) * motzkin` to be a sum of squares + +optimize!(model) + +# Now the problem is declared feasible by the solver... + +@test termination_status(model) == MOI.OPTIMAL #src +termination_status(model) + +# ... and the primal solution is a feasible point, hence it is a certificate of nonnegativity of the Motzkin polynomial. + +@test primal_status(model) == MOI.FEASIBLE_POINT #src +primal_status(model) + +# One may consider ourself lucky to have had the intuition that $x^2 + y^2$ would work as denominator. +# In fact, the search for the denominator can be carried out in parallel to the search of the numerator. +# In the example below, we search for a denominator with monomials of degrees from 0 to 2. +# If none is found, we can increase the maximum degree 2 to 4, 6, 8, ... +# This gives a hierarchy of programs to try in order to certify the nonnegativity of a polynomial by identifying it with a fraction of sum of squares polynomials. +# In the case of the Motzkin polynomial we now that degree 2 is enough since $x^2 + y^2$ works. + +model = SOSModel(solver) +X = monomials([x, y], 0:2) + +# We create a quadratic polynomial that is not necessarily a sum of squares since this is implied by the next constraint: `deno >= 1`. + +@variable(model, deno, Poly(X)) + +# We want the denominator polynomial to be strictly positive, this prevents the trivial solution deno = 0 for instance. + +@constraint(model, deno >= 1) +@constraint(model, deno * motzkin >= 0) +optimize!(model) + +@test termination_status(model) == MOI.OPTIMAL #src +termination_status(model) + +@test primal_status(model) == MOI.FEASIBLE_POINT #src +primal_status(model) + +# We can check the denominator found by the program using `JuMP.value` + +value(deno) + +# Because a picture is worth a thousand words let's plot the beast. +# We can easily extend `Plots` by adding a recipe to plot bivariate polynomials. + +using RecipesBase +@recipe function f(x::AbstractVector, y::AbstractVector, p::Polynomial) + x, y, (x, y) -> p(variables(p) => [x, y]) +end +import Plots +Plots.plot( + range(-2, stop=2, length=100), + range(-2, stop=2, length=100), + motzkin, + st = [:surface], + seriescolor=:heat, + colorbar=:none, + clims = (-10, 80) +) diff --git a/previews/PR347/tutorials/Getting started/sos_decomposition.jl b/previews/PR347/tutorials/Getting started/sos_decomposition.jl new file mode 100644 index 000000000..32e85a1b9 --- /dev/null +++ b/previews/PR347/tutorials/Getting started/sos_decomposition.jl @@ -0,0 +1,66 @@ +# # A trivial SOS decomposition example + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/sos_decomposition.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/sos_decomposition.ipynb) +# **Contributed by**: votroto +# **Adapted from**: Examples 3.25 of [BPT12] +# +# [BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. +# *Semidefinite Optimization and Convex Algebraic Geometry*. +# Society for Industrial and Applied Mathematics, **2012**. + +using Test #src +using DynamicPolynomials +using SumOfSquares +import CSDP + +# The polynomial `p = x^2 - x*y^2 + y^4 + 1` is SOS. +# We can, for example, decompose it as +# `p = 3/4*(x - y^2)^2 + 1/4*(x + y)^2 + 1`, +# which clearly proves that `p` is SOS, and there are infinitely many other ways +# to decompose `p` into sums of squares. + +# We can use SumOfSquares.jl to find such decompositions. + +# First, setup the polynomial of interest. + +@polyvar x y +p = x^2 - x*y^2 + y^4 + 1 + +# Secondly, constrain the polynomial to be nonnegative. +# SumOfSquares.jl transparently reinterprets polyonmial nonnegativity as the +# appropriate SOS certificate for polynomials nonnegative on semialgebraic sets. + +model = SOSModel(CSDP.Optimizer) +@constraint(model, cref, p >= 0) + +# Thirdly, optimize the feasibility problem! + +optimize!(model) + +# Lastly, recover a SOS decomposition. +# In general, SOS decompositions are not unique! + +sos_dec = sos_decomposition(cref, 1e-4) + +# Converting, rounding, and simplifying - Huzza, Back where we began! + +polynomial(sos_dec, Float32) + +# ## A deeper explanation and the unexplained `1e-4` parameter + +# `p = x^2 - x*y^2 + y^4 + 1` can be represented in terms of its Gram matrix as + +gram = gram_matrix(cref) + +#- + +gram.basis.monomials' * gram.Q * gram.basis.monomials + +# where the matrix `gram.Q` is positive semidefinite, because `p` is SOS. If we +# could only get the decomposition `gram.Q = V' * V`, the SOS decomposition would +# simply be `||V * monomials||^2`. + +# Unfortunately, we can not use Cholesky decomposition, since gram `Q` is only +# semidefinite, not definite. Hence, SumOfSquares.jl uses SVD decomposition +# instead and discards small singular values (in our case `1e-4`). diff --git a/previews/PR347/tutorials/Getting started/sum-of-squares_matrices.jl b/previews/PR347/tutorials/Getting started/sum-of-squares_matrices.jl new file mode 100644 index 000000000..8f4f07740 --- /dev/null +++ b/previews/PR347/tutorials/Getting started/sum-of-squares_matrices.jl @@ -0,0 +1,97 @@ +# # Sum-of-Squares matrices + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/sum-of-squares_matrices.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/sum-of-squares_matrices.ipynb) +# **Adapted from**: Examples 3.77 of [BPT12] +# +# [BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. +# *Semidefinite Optimization and Convex Algebraic Geometry*. +# Society for Industrial and Applied Mathematics, **2012**. + + +# ### Introduction + +# Consider the symmetric polynomial matrix +# $$P(x) = +# \begin{bmatrix} +# x^2 - 2x + 2 & x\\ +# x & x^2 +# \end{bmatrix}.$$ +# We could like to know whether $P(x)$ is positive semidefinite for all $x \in \mathbb{R}$. + +using Test #src +using DynamicPolynomials +@polyvar x +P = [x^2 - 2x + 2 x + x x^2] + +# A sufficient condition for a symmetric polynomial matrix $P(x)$ to be positive semidefinite for all $x$ is to the existence of a matrix $M(x)$ such that $P(x) = M^\top(x) M(x)$. If such matrix $M$ exists, we say that the matrix is an \emph{sos matrix} (see [Definition 3.76, BPT13]). +# While determining whether $P(x)$ is positive semidefinite for all $x$, is NP-hard (checking nonnegativity of a polynomial is reduced to this problem for $1 \times 1$ matrices), checking whether $P(x)$ is an sos matrix is an sos program. + +using SumOfSquares + +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + +model = SOSModel(solver) +mat_cref = @constraint(model, P in PSDCone()) +optimize!(model) +@test termination_status(model) == MOI.OPTIMAL #src +termination_status(model) + +# While the reformulation of sos matrix to sos polynomial is rather simple, as explained in the "Sum-of-Squares reformulation" section below, there is a technical subtelty about the Newton polytope that if not handled correctly may result in an SDP of large size with bad numerical behavior. For this reason, it is recommended to model sos *matrix* constraints as such as will be shown in this notebook and not do the formulation manually unless there is a specific reason to do so. +# +# As we can verify as follows, only 3 monomials are used using the sos *matrix* constraint. + +@test length(certificate_monomials(mat_cref)) == 3 #src +certificate_monomials(mat_cref) #!jl + +# ### Sum-of-Squares reformulation +# +# One way to obtain the reduction to an sos program is to create an intermediate vector of variable $y$ and check whether the polynomial $p(x, y) = y^\top P(x) y$ is sos. +# However, special care is required when approximating the Newton polytope of $p(x, y)$. +# Indeed, for instance if the entries of $P(x)$ are quadratic forms then the Newton polytope of $p(x, y)$ is the cartesian product between the Newton polytope of $y^\top y$ and the Newton polytope of $x^\top x$. +# In other words, $p(x, y)$ belongs to a family of quartic forms called biquadratic forms. +# This fact is important when generating the semidefinite program so that only bilinear monomials are used. +# So if the cheap outer approximation is used (instead of the exact polyhedral computation) for the newton polytope then it is important to use a multipartite computation approximation of the newton polytope. +# The multipartie exact approach may perform worse compared to the unipartite exact in certain cases though. +# Consider for instance the polynomial matrix $\mathrm{Diag}(x_1^1, x_2^2)$ for which $p(x, y) = x_1^2y_1^2 + x_2^2y_2^2$. +# For this polynomial, only the monomials $x_1y_1$ and $x_2y_2$ are needed in the SDP reformulation while the multipartite approach, +# as it will compute the Newton polytope as a cartesian product, will not see the dependence between $x$ and $y$ in the presence of monomials and will also select the monomials $x_1y_2$ and $x_2y_1$. + +@polyvar y[1:2] +p = vec(y)' * P * vec(y) + +# We can see above that `p` is biquadratic polynomial in the variables `x` and `y`. +# Computing the Newton polytope with the cheap outer approximation +# without exploiting this multipartite structure gives the following 6 monomials. + +X = monomials(p) +unipartite = Certificate.NewtonDegreeBounds(tuple()) +@test Certificate.monomials_half_newton_polytope(X, unipartite) == [x * y[1], x * y[2], y[1] * y[2], x, y[1], y[2]] #src +Certificate.monomials_half_newton_polytope(X, unipartite) #!jl + +# Exploiting the multipartite structure gives 4 monomials. + +multipartite = Certificate.NewtonDegreeBounds(([x], y)) +@test Certificate.monomials_half_newton_polytope(X, multipartite) == [x * y[1], x * y[2], y[1], y[2]] #src +Certificate.monomials_half_newton_polytope(X, multipartite) #!jl + +# In the example above, there were only 3 monomials, where does the difference come from ? +# Using the monomial basis, the only product of two monomials that is equal to +# `y[2]^2` is `y[2] * y[2]`. As `y[2]^2` is not a monomial of `p`, we can conclude +# that the diagonal entry with row and column corresponding to `y[2]` will be zero +# hence the whole column and row will be zero as well. +# Therefore, we can remove this monomial. + +@test Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(multipartite)) == [x * y[1], x * y[2], y[1]] #src +Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(multipartite)) #!jl + +# The same reasoning can be used for monomials `y[1]y[2]` and `x` therefore whether +# we exploit the multipartite structure or not, we get only 3 monomials thanks +# to this post filter. + +@test Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(unipartite)) == [x * y[1], x * y[2], y[1]] #src +Certificate.monomials_half_newton_polytope(X, Certificate.NewtonFilter(unipartite)) #!jl diff --git a/previews/PR347/tutorials/Getting started/univariate.jl b/previews/PR347/tutorials/Getting started/univariate.jl new file mode 100644 index 000000000..3d8dad5aa --- /dev/null +++ b/previews/PR347/tutorials/Getting started/univariate.jl @@ -0,0 +1,116 @@ +# # Minimization of a univariate polynomial + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Getting started/univariate.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Getting started/univariate.ipynb) +# **Contributed by**: Benoît Legat + +using Test #src +using DynamicPolynomials +using SumOfSquares +import CSDP + +# Consider the problem of finding both the minimum value of `p = x^4 - 4x^3 - 2x^2 + 12x + 3` as well as its minimizers. + +# We can use SumOfSquares.jl to find such these values as follows. +# We first define the polynomial using DynamicPolynomials. + +@polyvar x +p = x^4 - 4x^3 - 2x^2 + 12x + 3 + +# Secondly, we create a Sum-of-Squares program searching for the maximal lower bound `σ` of the polynomial. + +model = SOSModel(CSDP.Optimizer) +@variable(model, σ) +@constraint(model, cref, p >= σ) +@objective(model, Max, σ) + +# Thirdly, solve the program and find `σ = -6` as lower bound: + +optimize!(model) +solution_summary(model) + +# We can look at the certificate that `σ = -6` is a lower bound: + +sos_dec = sos_decomposition(cref, 1e-4) +expected = x^2 - 2x - 3 #src +@test isapprox(sos_dec.ps, [expected], rtol=1e-4) || isapprox(sos_dec.ps, [-expected], rtol=1e-4) #src + +# Indeed, `p + 6 = (x^2 - 2x - 3)^2` so `p ≥ -6`. +# +# ## Extraction of minimizers +# +# We can now find the minimizers from the moment matrix: + +ν = moment_matrix(cref) +ν.Q + +# This matrix is the convex combination of the moment matrices corresponding to two atomic measures at `-1` and `3` +# which allows us to conclude that `-1` and `3` are global minimizers. + +η = atomic_measure(ν, 1e-4) +minimizers = [η.atoms[1].center; η.atoms[2].center] + +# Below are more details on what we mean by convex combination. +# The moment matrix of the atomic measure at the first minimizer is: + +η1 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[1])), ν.basis.monomials) +η1.Q + +# The moment matrix of the atomic measure at the second minimizer is: + +η2 = moment_matrix(dirac(monomials(x, 0:4), x => round(minimizers[2])), ν.basis.monomials) +η2.Q + +# And the moment matrix is the convex combination of both: + +Q12 = η1.Q * η.atoms[1].weight + η2.Q * η.atoms[2].weight +@test ν.Q ≈ Q12 rtol=1e-6 #src + +# Another way to see this (by linearity of the expectation) is that `ν` is the moment matrix +# of the convex combination of the two atomic measures. + +# ## Changing the polynomial basis +# +# The monomial basis used by default can leave a problem quite ill-conditioned for the solver. +# Let's try to use another basis instead: + +model = SOSModel(CSDP.Optimizer) +@variable(model, σ) +@constraint(model, cheby_cref, p >= σ, basis = ChebyshevBasisFirstKind) +@objective(model, Max, σ) +optimize!(model) +solution_summary(model) + +# Although the gram matrix in the monomial basis: + +g = gram_matrix(cref) +@show g.basis +g.Q + +# looks different from the gram matrix in the Chebyshev basis: + +cheby_g = gram_matrix(cheby_cref) +@show cheby_g.basis +cheby_g.Q + +@test polynomial(g) ≈ polynomial(cheby_g) rtol=1e-4 #src + +# they both yields the same Sum-of-Squares decomposition: + +cheby_sos_dec = sos_decomposition(cheby_cref, 1e-4) +@test isapprox(cheby_sos_dec.ps, [expected], rtol=1e-4) || isapprox(cheby_sos_dec.ps, [-expected], rtol=1e-4) #src + +# The gram matrix in the Chebyshev basis can be understood as follows. +# To express the polynomial $-x^2 + 2x + 3$ in the Chebyshev basis, we start by +# substituting $x$ into $\cos(\theta)$ to obtain +# $-\cos(\theta)^2 + 2\cos(\theta) + 3$. +# We now express it as a combination of $\cos(n\theta)$ for $n = 0, 1, 2$: +# $-(2\cos(\theta) - 1) /2 + 2 \cos(\theta) + 5/2.$ +# Therefore, the coefficients in the Chebyshev basis is: + +cheby_coefs = [5/2, 2, -1/2] + +# We can indeed observe that we obtain the same matrix as `cheby_g.Q` + +@test cheby_g.Q ≈ cheby_coefs * cheby_coefs' rtol=1e-6 #src +cheby_coefs * cheby_coefs' diff --git a/previews/PR347/tutorials/Noncommutative and Hermitian/noncommutative_variables.jl b/previews/PR347/tutorials/Noncommutative and Hermitian/noncommutative_variables.jl new file mode 100644 index 000000000..0c25b029e --- /dev/null +++ b/previews/PR347/tutorials/Noncommutative and Hermitian/noncommutative_variables.jl @@ -0,0 +1,73 @@ +# # Noncommutative variables + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Noncommutative and Hermitian/noncommutative_variables.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Noncommutative and Hermitian/noncommutative_variables.ipynb) +# **Adapted from**: Examples 2.11 and 2.2 of [BKP16] +# +# [BKP16] Sabine Burgdorf, Igor Klep, and Janez Povh. +# *Optimization of polynomials in non-commuting variables*. +# Berlin: Springer, 2016. + +# ## Example 2.11 +# +# We consider the Example 2.11 of [BKP16] in which the polynomial with noncommutative variables +# $(x * y + x^2)^2 = x^4 + x^3y + xyx^2 + xyxy$ is tested to be sum-of-squares. + +using Test #src +using DynamicPolynomials +@ncpolyvar x y +p = (x * y + x^2)^2 + +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +using SumOfSquares +import CSDP +optimizer_constructor = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = Model(optimizer_constructor) +con_ref = @constraint(model, p in SOSCone()) + +optimize!(model) + +# We see that both the monomials `xy` and `yx` are considered separately, this is a difference with the commutative version. + +certificate_basis(con_ref) + +# We see that the solution correctly uses the monomial `xy` instead of `yx`. We also identify that only the monomials `x^2` and `xy` would be needed. This would be dectected by the Newton chip method of [Section 2.3, BKP16]. + +gram_matrix(con_ref).Q + +# When asking for the SOS decomposition, the numerically small entries makes the solution less readable. + +@test length(sos_decomposition(con_ref).ps) == 2 #src +sos_decomposition(con_ref) + +# They are however easily discarded by using a nonzero tolerance: + +dec = sos_decomposition(con_ref, 1e-6) #src +@test length(dec.ps) == 1 #src +@test sign(first(coefficients(dec.ps[1]))) * dec.ps[1] ≈ x * y + x^2 rtol=1e-5 atol=1e-5 #src +sos_decomposition(con_ref, 1e-6) + +# ## Example 2.2 +# +# We consider now the Example 2.2 of [BKP16] in which the polynomial with noncommutative variables +# $(x + x^{10}y^{20}x^{10})^2$ is tested to be sum-of-squares. + +using DynamicPolynomials +@ncpolyvar x y +n = 10 +p = (x + x^n * y^(2n) * x^n)^2 + +using SumOfSquares +model = Model(optimizer_constructor) +con_ref = @constraint(model, p in SOSCone()) + +optimize!(model) + +# Only two monomials were considered for the basis of the gram matrix thanks to the Augmented Newton chip method detailed in [Section 2.4, BKP16]. + +certificate_basis(con_ref) + +gram_matrix(con_ref).Q + +sos_decomposition(con_ref, 1e-6) diff --git a/previews/PR347/tutorials/Noncommutative and Hermitian/sums_of_hermitian_squares.jl b/previews/PR347/tutorials/Noncommutative and Hermitian/sums_of_hermitian_squares.jl new file mode 100644 index 000000000..f829f3c80 --- /dev/null +++ b/previews/PR347/tutorials/Noncommutative and Hermitian/sums_of_hermitian_squares.jl @@ -0,0 +1,24 @@ +# # Sums of Hermitian squares + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Noncommutative and Hermitian/sums_of_hermitian_squares.ipynb) +# **Contributed by**: Benoît Legat + +using Test #src + +using SumOfSquares + +using DynamicPolynomials +@ncpolyvar x y +p = (x + im * y) * (x - im * y) + +import CSDP +model = Model(CSDP.Optimizer) +cone = NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}() +con_ref = @constraint(model, p in cone) +optimize!(model) +dec = sos_decomposition(con_ref, 1e-6) #src +@test length(dec.ps) == 1 #src +@test dec.ps[1]' * dec.ps[1] ≈ p atol=1e-6 rtol=1e-6 #src +@test sign(real(first(coefficients(dec.ps[1])))) * dec.ps[1] ≈ y + im * x atol=1e-6 rtol=1e-6 #src +sos_decomposition(con_ref, 1e-6) diff --git a/previews/PR347/tutorials/Other Applications/bounds_in_probability.jl b/previews/PR347/tutorials/Other Applications/bounds_in_probability.jl new file mode 100644 index 000000000..8086e06c3 --- /dev/null +++ b/previews/PR347/tutorials/Other Applications/bounds_in_probability.jl @@ -0,0 +1,74 @@ +# # Bounds in Probability + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Other Applications/bounds_in_probability.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Other Applications/bounds_in_probability.ipynb) +# **Adapted from**: SOSTOOLS' SOSDEMO8 (See Section 4.8 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf)) + +using Test #src + +# The probability adds up to one. + +μ0 = 1 + +# The mean is one. + +μ1 = 1 + +# The standard deviation is 1/2. + +σ = 1/2 + +# The second moment `E(x^2)` is: + +μ2 = σ^2 + μ1^2 + +# We define the moments as follows: + +using DynamicPolynomials +@polyvar x +monos = [1, x, x^2] +using SumOfSquares +μ = measure([μ0, μ1, μ2], monos) + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints. + +using CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +# We create a polynomial with the monomials in `monos` and +# JuMP decision variables as coefficients as follows: + +@variable(model, poly, Poly(monos)) + +# Nonnegative on the support: + +K = @set 0 <= x && x <= 5 +con_ref = @constraint(model, poly >= 0, domain = K) + +# Greater than one on the event: + +@constraint(model, poly >= 1, domain = (@set 4 <= x && x <= 5)) + +# The bound (we use `LinearAlgebra` for the `⋅` syntax for the scalar product): + +using LinearAlgebra +@objective(model, Min, poly ⋅ μ) + +# We verify that we found a feasible solution: + +optimize!(model) +@test primal_status(model) == MOI.FEASIBLE_POINT #src +primal_status(model) + +# The objective value is `1/37`: + +@test isapprox(objective_value(model), 1/37, rtol=1e-5) #src +objective_value(model) + +# The solution is `(12x-11)^2 / 37^2`: + +@test sos_decomposition(con_ref, K, 1e-4) isa SOSDecompositionWithDomain #src +@test isapprox(value(poly), ((12/37)x-11/37)^2, rtol=1e-3) #src +value(poly) * 37^2 diff --git a/previews/PR347/tutorials/Polynomial Optimization/bilinear.jl b/previews/PR347/tutorials/Polynomial Optimization/bilinear.jl new file mode 100644 index 000000000..6ee1f7204 --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/bilinear.jl @@ -0,0 +1,55 @@ +# # Bilinear terms + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/bilinear.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/bilinear.ipynb) +# **Adapted from**: [Floudas1999; Section 3.1](@cite) and [Lasserre2009; Table 5.1](@cite) + +# ## Introduction + +# Consider the polynomial optimization problem from [Floudas1999; Section 3.1](@cite). + +using Test #src +using DynamicPolynomials +@polyvar x[1:8] +p = sum(x[1:3]) +using SumOfSquares +K = @set 0.0025 * (x[4] + x[6]) <= 1 && + 0.0025 * (-x[4] + x[5] + x[7]) <= 1 && + 0.01 * (-x[5] + x[8]) <= 1 && + 100x[1] - x[1] * x[6] + 8333.33252x[4] <= 250000/3 && + x[2] * x[4] - x[2] * x[7] - 1250x[4] + 1250x[5] <= 0 && + x[3] * x[5] - x[3] * x[8] - 2500x[5] + 1250000 <= 0 && + 100 <= x[1] && x[1] <= 10000 && + 1000 <= x[2] && x[2] <= 10000 && + 1000 <= x[3] && x[3] <= 10000 && + 10 <= x[4] && x[4] <= 1000 && + 10 <= x[5] && x[5] <= 1000 && + 10 <= x[6] && x[6] <= 1000 && + 10 <= x[7] && x[7] <= 1000 && + 10 <= x[8] && x[8] <= 1000 + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import Clarabel +solver = Clarabel.Optimizer + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`. + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +# The first level of the hierarchy gives a lower bound of `2100` + +model2 = solve(2) +nothing # hide +@test objective_value(model2) ≈ 2100 rtol=1e-4 #src +@test termination_status(model2) == MOI.OPTIMAL #src diff --git a/previews/PR347/tutorials/Polynomial Optimization/bound_on_global_extremum.jl b/previews/PR347/tutorials/Polynomial Optimization/bound_on_global_extremum.jl new file mode 100644 index 000000000..2d3fa94eb --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/bound_on_global_extremum.jl @@ -0,0 +1,48 @@ +# # Bound on Global Extremum + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/bound_on_blobal_extremum.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/bound_on_global_extremum.ipynb) +# **Adapted from**: SOSTOOLS' SOSDEMO3 (See Section 4.3 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf)) + +using Test #src +using DynamicPolynomials +@polyvar x1 x2 + +# The Goldstein-Price function $f(x)$ is defined as follows: + +f1 = x1 + x2 + 1 +f2 = 19 - 14x1 + 3x1^2 - 14x2 + 6x1*x2 + 3x2^2 +f3 = 2x1 - 3x2 +f4 = 18 - 32x1 + 12x1^2 + 48x2 - 36x1*x2 + 27x2^2 +f = (1 + f1^2 * f2) * (30 + f3^2 * f4) + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints. + +using SumOfSquares +using CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +# We create the decision variable $\gamma$ that will be the lower bound to the Goldstein-Price function. +# We maximize it to have the highest possible lower bound. + +@variable(model, γ) +@objective(model, Max, γ) + +# We constrain $\gamma$ to be a lower bound with the following constraint +# that ensures that $f(x_1, x_2) \ge \gamma$ for all $x_1, x_2$. + +@constraint(model, f >= γ) + +JuMP.optimize!(model) + +# We verify that the solver has found a feasible solution: + +JuMP.primal_status(model) +@test JuMP.primal_status(model) == MOI.FEASIBLE_POINT || JuMP.primal_status(model) == MOI.NEARLY_FEASIBLE_POINT #src + +# We can now obtain the lower bound either with `value(γ)` or `objective_value(model)`: + +objective_value(model) +@test objective_value(model) ≈ 3 rtol=1e-2 #src diff --git a/previews/PR347/tutorials/Polynomial Optimization/ellipsoid.jl b/previews/PR347/tutorials/Polynomial Optimization/ellipsoid.jl new file mode 100644 index 000000000..f91872087 --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/ellipsoid.jl @@ -0,0 +1,73 @@ +# # Exterior of ellipsoid + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/ellipsoid.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/ellipsoid.ipynb) +# **Adapted from**: [Floudas1999; Section 3.5](@cite) and [Lasserre2009; Table 5.1](@cite) + +# ## Introduction + +# Consider the polynomial optimization problem from [Floudas1999; Section 3.5](@cite) + +A = [ + 0 0 1 + 0 -1 0 + -2 1 -1 +] +bz = [3, 0, -4] - [0, -1, -6] +y = [1.5, -0.5, -5] + +using Test #src +using DynamicPolynomials +@polyvar x[1:3] +p = -2x[1] + x[2] - x[3] +using SumOfSquares +e = A * x - y +f = e'e - bz'bz / 4 +K = @set sum(x) <= 4 && 3x[2] + x[3] <= 6 && f >= 0 && 0 <= x[1] && x[1] <= 2 && 0 <= x[2] && 0 <= x[3] && x[3] <= 3 + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import Clarabel +solver = Clarabel.Optimizer + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`. + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +# The first level of the hierarchy gives a lower bound of `-7`` + +model2 = solve(2) +nothing # hide +@test objective_value(model2) ≈ -6 rtol=1e-4 #src +@test termination_status(model2) == MOI.OPTIMAL #src + +# The second level improves the lower bound + +model4 = solve(4) +nothing # hide +@test objective_value(model4) ≈ -74/13 rtol=1e-4 #src +@test termination_status(model4) == MOI.OPTIMAL #src + +# The third level improves it even further + +model6 = solve(6) +nothing # hide +@test objective_value(model6) ≈ -4.06848 rtol=1e-4 #src +@test termination_status(model6) == MOI.OPTIMAL #src + +# The fourth level finds the optimal objective value as lower bound. + +model8 = solve(8) +nothing # hide +@test objective_value(model8) ≈ -4 rtol=1e-4 #src +@test termination_status(model8) == MOI.OPTIMAL #src diff --git a/previews/PR347/tutorials/Polynomial Optimization/goldstein_price.jl b/previews/PR347/tutorials/Polynomial Optimization/goldstein_price.jl new file mode 100644 index 000000000..f4b0a7c4f --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/goldstein_price.jl @@ -0,0 +1,85 @@ +# # Goldstein-price function + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/goldstein_price.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/goldstein_price.ipynb) +# **Contributed by**: Benoît Legat + +# In this example, we consider the minimization of the [Goldstein-price function](https://en.wikipedia.org/wiki/Test_functions_for_optimization). + +using Test #src +using SumOfSquares +using DynamicPolynomials + +# Create *symbolic* variables (not JuMP *decision* variables) + +@polyvar x[1:2] + +# To use Sum-of-Squares Programming, we first need to pick an SDP solver, +# see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import Clarabel +using Dualization +model = SOSModel(dual_optimizer(Clarabel.Optimizer)) + +# Create a JuMP decision variable for the lower bound + +@variable(model, γ) + +# `f(x)` is the Goldstein-Price function + +f1 = x[1] + x[2] + 1 +f2 = 19 - 14*x[1] + 3*x[1]^2 - 14*x[2] + 6*x[1]*x[2] + 3*x[2]^2 +f3 = 2*x[1] - 3*x[2] +f4 = 18 - 32*x[1] + 12*x[1]^2 + 48*x[2] - 36*x[1]*x[2] + 27*x[2]^2 +f = (1 + f1^2*f2) * (30 + f3^2*f4) + +# Constraints `f(x) - γ` to be a sum of squares + +con_ref = @constraint(model, f >= γ) +@objective(model, Max, γ) +optimize!(model) + +# The lower bound found is 3 + +@test objective_value(model) ≈ 3 rtol=1e-3 #src +solution_summary(model) + +# The moment matrix is as follows, we can already see the global minimizer +# `[0, -1]` from the entries `(2, 1)` and `(3, 1)`. +# This heuristic way to obtain solutions to the polynomial optimization problem +# is suggested in [Laurent2008; (6.15)](@cite). + +ν = moment_matrix(con_ref) + +# Many entries of the matrix actually have the same moment. +# We can obtain the following list of these moments without duplicates +# (ignoring when difference of entries representing the same moments is below `1e-5`) + +μ = measure(ν, atol = 1e-5) + +# The truncated moment matrix can then be obtained as follows + +ν_truncated = moment_matrix(μ, monomials(x, 0:3)) + +# Let's check if the flatness property is satisfied. +# The rank of `ν_truncated` seems to be 1: + +using LinearAlgebra +LinearAlgebra.svdvals(Matrix(ν_truncated.Q)) +LinearAlgebra.rank(Matrix(ν_truncated.Q), rtol = 1e-3) +@test LinearAlgebra.rank(Matrix(ν_truncated.Q), rtol = 1e-3) == 1 #src +svdvals(Matrix(ν_truncated.Q)) + +# The rank of `ν` is clearly higher than 1, closer to 3: + +@test 3 <= LinearAlgebra.rank(Matrix(ν.Q), rtol = 1e-3) <= 4 #src +svdvals(Matrix(ν.Q)) + +# Even if the flatness property is not satisfied, we can +# still try extracting the minimizer with a low rank decomposition of rank 3. +# We find the optimal solution again doing so: + +atoms = atomic_measure(ν, FixedRank(3)) #src +@test length(atoms.atoms) == 1 #src +@test atoms.atoms[1].center ≈ [0, -1] rtol=1e-3 #src +atomic_measure(ν, FixedRank(3)) diff --git a/previews/PR347/tutorials/Polynomial Optimization/min_univariate.jl b/previews/PR347/tutorials/Polynomial Optimization/min_univariate.jl new file mode 100644 index 000000000..3bf6fef4d --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/min_univariate.jl @@ -0,0 +1,90 @@ +# # Maximizing as minimum + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/min_univariate.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/min_univariate.ipynb) +# **Adapted from**: [Floudas1999; Section 4.10](@cite), [Laurent2008; Example 6.23](@cite) and [Lasserre2009; Table 5.1](@cite) + +# ## Introduction + +# Consider the polynomial optimization problem from [Floudas1999; Section 4.10](@cite) +# of minimizing the linear function $-x_1 - x_2$ +# over the basic semialgebraic set defined by the inequalities +# $x_2 \le 2x_1^4 - 8x_1^3 + 8x_1^2 + 2$, +# $x_2 \le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36$ and the box constraints +# $0 \le x_1 \le 3$ and $0 \le x_2 \le 4$, + +using Test #src +using DynamicPolynomials +@polyvar x[1:2] +p = -sum(x) +using SumOfSquares +f1 = 2x[1]^4 - 8x[1]^3 + 8x[1]^2 + 2 +f2 = 4x[1]^4 - 32x[1]^3 + 88x[1]^2 - 96x[1] + 36 +K = @set x[1] >= 0 && x[1] <= 3 && x[2] >= 0 && x[2] <= 4 && x[2] <= f1 && x[2] <= f2 + +# As we can observe below, the bounds on `x[2]` could be dropped and +# optimization problem is equivalent to the maximization of `min(f1, f2)` +# between `0` and `3`. + +xs = range(0, stop = 3, length = 100) +using Plots +plot(xs, f1.(xs), label = "f1") +plot!(xs, f2.(xs), label = "f2") +plot!(xs, 4 * ones(length(xs)), label = nothing) + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import Clarabel +solver = Clarabel.Optimizer + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`. + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +# The first level of the hierarchy gives a lower bound of `-7`` + +model4 = solve(4) +nothing # hide +@test objective_value(model4) ≈ -7 rtol=1e-4 #src +@test termination_status(model4) == MOI.OPTIMAL #src + +# The second level improves the lower bound + +model5 = solve(5) +nothing # hide +@test objective_value(model5) ≈ -20/3 rtol=1e-4 #src +@test termination_status(model5) == MOI.OPTIMAL #src + +# The third level finds the optimal objective value as lower bound... + +model7 = solve(7) +nothing # hide +@test objective_value(model7) ≈ -5.5080 rtol=1e-4 #src +@test termination_status(model7) == MOI.OPTIMAL #src + +# ...and proves it by exhibiting the minimizer. + +ν7 = moment_matrix(model7[:c]) +η = atomic_measure(ν7, 1e-3) # Returns nothing as the dual is not atomic +@test length(η.atoms) == 1 #src +@test η.atoms[1].center ≈ [2.3295, 3.1785] rtol=1e-4 #src + +# We can indeed verify that the objective value at `x_opt` is equal to the lower bound. + +x_opt = η.atoms[1].center +@test x_opt ≈ [2.3295, 3.1785] rtol=1e-4 #src +p(x_opt) + +# We can see visualize the solution as follows: + +scatter!([x_opt[1]], [x_opt[2]], markershape = :star, label = nothing) diff --git a/previews/PR347/tutorials/Polynomial Optimization/polynomial_optimization.jl b/previews/PR347/tutorials/Polynomial Optimization/polynomial_optimization.jl new file mode 100644 index 000000000..4cb550869 --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/polynomial_optimization.jl @@ -0,0 +1,315 @@ +# # Polynomial Optimization + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/polynomial_optimization.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/polynomial_optimization.ipynb) +# **Contributed by**: Benoît Legat + +# ## Introduction + +# Consider the polynomial optimization problem [Lasserre2009; Example 2.2](@cite) of +# minimizing the polynomial $x^3 - x^2 + 2xy - y^2 + y^3$ +# over the polyhedron defined by the inequalities $x \ge 0, y \ge 0$ and $x + y \geq 1$. + +using Test #src +using DynamicPolynomials +@polyvar x y +p = x^3 - x^2 + 2x*y -y^2 + y^3 +using SumOfSquares +S = @set x >= 0 && y >= 0 && x + y >= 1 +p(x=>1, y=>0), p(x=>1//2, y=>1//2), p(x=>0, y=>1) + +# ## Local search + +# A local solver only uses the **local** information given by the the value, gradient and hessian +# of the objective function and constraints at a given solution. When it converges, it therefore only +# guarantees that the found solution is a **local** minimum. +# In this example, the optimal solutions are $(x, y) = (1, 0)$ and $(x, y) = (0, 1)$ with objective value $0$ but +# [Ipopt](https://github.com/jump-dev/Ipopt.jl/) only finds the local minimum $(1/2, 1/2)$ with objective value $1/4$. + +import Ipopt +model = Model(Ipopt.Optimizer) +@variable(model, a >= 0) +@variable(model, b >= 0) +@constraint(model, a + b >= 1) +@NLobjective(model, Min, a^3 - a^2 + 2a*b - b^2 + b^3) +optimize!(model) + +# As we can see below, the termination status is `LOCALLY_SOLVED` and not of `OPTIMAL` +# because Ipopt only guarantees **local** optimality. + +@test termination_status(model) == MOI.LOCALLY_SOLVED #src +@test objective_value(model) ≈ 0.25 rtol=1e-5 #src +solution_summary(model) + +# Indeed, the solution found is not globally optimal: + +@test value(a) ≈ 0.5 rtol=1e-5 #src +@test value(b) ≈ 0.5 rtol=1e-5 #src +value(a), value(b) + +# Note that the problem can be written equivalently as follows using [registered functions](https://jump.dev/JuMP.jl/stable/manual/nlp/#Register-a-function). +# The difference is that the gradient and hessian will be computed via the *Symbolic Differentiation* provided +# by MultivariatePolynomials instead of JuMP's *Automatic Differentiation*: + +f(a, b) = p(x => a, y => b) +∇p = differentiate(p, [x, y]) +function ∇f(g, a, b) + for i in eachindex(g) + g[i] = ∇p[i](x => a, y => b) + end +end +∇²p = differentiate(∇p, [x, y]) +function ∇²f(H, a, b) + for j in axes(∇²p, 2) + for i in j:size(∇²p, 1) + H[i, j] = ∇²p[i, j](x => a, y => b) + end + end +end +using Ipopt +gmodel = Model(Ipopt.Optimizer) +@variable(gmodel, a >= 0) +@variable(gmodel, b >= 0) +@constraint(gmodel, a + b >= 1) +register(gmodel, :f, 2, f, ∇f, ∇²f) +@NLobjective(gmodel, Min, f(a, b)) +optimize!(gmodel) + +# Even if we have the algebraic expressions of gradient and hessian, +# Ipopt is not using these symbolic expressions but only local information +# hence it can still only provide local guarantees: + +@test termination_status(gmodel) == MOI.LOCALLY_SOLVED #src +@test objective_value(gmodel) ≈ 0.25 rtol=1e-5 #src +solution_summary(gmodel) + +# and the same solution is found: + +@test value(a) ≈ 0.5 rtol=1e-5 #src +@test value(b) ≈ 0.5 rtol=1e-5 #src +value(a), value(b) + +# ## Sum-of-Squares approach + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import SCS +scs = SCS.Optimizer +import Dualization +dual_scs = Dualization.dual_optimizer(scs) + + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following program searches for the largest lower bound and finds zero. + +model = SOSModel(dual_scs) +@variable(model, α) +@objective(model, Max, α) +@constraint(model, c3, p >= α, domain = S) +optimize!(model) + +# This time, the termination status is `OPTIMAL` but this does not necessarily mean that we found +# the optimal solution to the polynomial optimization problem. +# This only means that CSDP founds an optimal solution to the Sum-of-Squares relaxation. + +@test termination_status(model) == MOI.OPTIMAL #src +@test objective_value(model) ≈ 0.0 atol=1e-3 #src +solution_summary(model) + +# The feasibility of the primal solution guarantees that the objective value `0` is a lower bound +# to the polynomial optimization problem. +# The optimality means that it's the best lower bound we can get (at this degree of the hierarcy). +# Using the solution $(1/2, 1/2)$ found by Ipopt of objective value $1/4$ +# and this certificate of lower bound $0$ we know that the optimal objective value is in the interval $[0, 1/4]$ +# but we still do not know what it is (if we consider that we did not try the solutions $(1, 0)$ and $(0, 1)$ as done in the introduction). +# If the dual of the constraint `c3` was atomic, its atoms would have given optimal solutions of objective value $0$ but that is not the case. + +ν3 = moment_matrix(c3) +@test atomic_measure(ν3, 1e-3) === nothing #src +atomic_measure(ν3, 1e-3) # Returns nothing as the dual is not atomic + +# Fortunately, there is a hierarchy of programs with increasingly better bounds that can be solved until we get one with atom dual variables. +# This comes from the way the Sum-of-Squares constraint with domain `S` is formulated. +# The polynomial $p - \alpha$ is guaranteed to be nonnegative over the domain `S` if there exists Sum-of-Squares polynomials $s_0$, $s_1$, $s_2$, $s_3$ such that +# ```math +# p - \alpha = s_0 + s_1 x + s_2 y + s_3 (x + y - 1). +# ``` +# Indeed, in the domain `S`, $x$, $y$ and $x + y - 1$ are nonnegative so the right-hand side is a sum of squares hence is nonnegative. +# Once the degrees of $s_1$, $s_2$ and $s_3$ have been decided, the degree needed for $s_0$ will be determined but we have a freedom in choosing the degrees of $s_1$, $s_2$ and $s_3$. +# By default, they are chosen so that the degrees of $s_1 x$, $s_2 y$ and $s_3 (x + y - 1)$ match those of $p - \alpha$ but this can be overwritten using the `maxdegree` keyword argument. + +# ### The maxdegree keyword argument + +# The maximum total degree (i.e. maximum sum of the exponents of $x$ and $y$) of the monomials of $p$ is 3 so the constraint in the program above is equivalent to `@constraint(model, p >= α, domain = S, maxdegree = 3)`. +# That is, since $x$, $y$ and $x + y - 1$ have total degree 1, the sum of squares polynomials $s_1$, $s_2$ and $s_3$ have been chosen with maximum total degree $2$. +# Since these polynomials are sums of squares, their degree must be even so the next maximum total degree to try is 4. +# For this reason, the keywords `maxdegree = 4` and `maxdegree = 5` have the same effect in this example. +# In general, if the polynomials in the domain are not all odd or all even, each value of `maxdegree` has a different effect in the choice of the maximum total degree of some $s_i$. + +model = SOSModel(dual_scs) +@variable(model, α) +@objective(model, Max, α) +@constraint(model, c4, p >= α, domain = S, maxdegree = 4) +optimize!(model) + +# We can see that the basis of the moment matrix didn't increase: + +@test length(moment_matrix(c4).basis.monomials) == 3 #src +moment_matrix(c4) + +# This is because of the Newton polytope reduction that determined that gram matrix will +# be zero for these degrees so it reduced the problem back to the equivalent of `maxdegree` 3 +# Let's turn this off with `newton_polytope = nothing` + +function sos(solver, deg) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = S, maxdegree = deg, newton_polytope = nothing) + optimize!(model) + @test termination_status(model) == MOI.OPTIMAL #src + @test objective_value(model) ≈ 0.0 atol=1e-3 #src + return model +end +dual_model4 = sos(dual_scs, 4) +nothing #hide + +# We see that the lower bound is still 0: + +solution_summary(dual_model4) + +# Let's now look at which solution we can extract from the moment matrix: + +dual_ν4 = moment_matrix(dual_model4[:c]) + +# Looking at the singular values, `4` seems to be a reasonable rank: + +using LinearAlgebra +svdvals(Matrix(dual_ν4.Q)) + +# The solution we extract is `(0.5, 0.5)` which is the solution found by Ipopt: + +dual_atoms4 = atomic_measure(dual_ν4, FixedRank(4)) #src +@test dual_atoms4.atoms[1].center ≈ [0.5, 0.5] rtol=1e-1 #src +atomic_measure(dual_ν4, FixedRank(4)) + +# This process is quite sensitive numerically so let's try to solve it without dualization as well: + +model4 = sos(scs, 4) +nothing #hide + +# We see that the lower bound is again 0: + +solution_summary(model4) + +# The moment matrix is the following + +ν4 = moment_matrix(model4[:c]) + +# Looking at the singular values, `3` seems to be a reasonable rank: + +svdvals(Matrix(ν4.Q)) + +# This time, the dual variable is atomic as it is the moments of the measure +# $$0.5 \delta(x-1, y) + 0.5 \delta(x, y-1)$$ +# where $\delta(x, y)$ is the dirac measure centered at $(0, 0)$. +# Therefore the program provides both a certificate that $0$ is a lower bound and a certificate that it is also an upper bound since it is attained at the global minimizers $(1, 0)$ and $(0, 1)$. + +atoms4 = atomic_measure(ν4, FixedRank(3)) #src +@test atoms4.atoms[1].center[2:-1:1] ≈ atoms4.atoms[2].center[1:2] rtol=1e-1 #src +atomic_measure(ν4, FixedRank(3)) + +# ## A deeper look into atom extraction + +# The moment matrix is transformed into a system of polynomials equations whose solutions give the atoms. +# This transformation uses the SVD decomposition of the moment matrix and discards the equations corresponding to the lowest singular values. +# When this system of equation has an infinite number of solutions, `atomic_measure` concludes that the measure is not atomic. +# For instance, with `maxdegree = 3`, we obtain the system +# $$x + y = 1$$ +# which contains a whole line of solution. +# This explains `atomic_measure` returned `nothing`. + +ν3 = moment_matrix(c3) +SumOfSquares.MultivariateMoments.compute_support!(ν3, LeadingRelativeRankTol(1e-3)) +@test length(ν3.support.I.p) == 1 #src + +# With `maxdegree = 4`, we obtain the system +# ```math +# \begin{aligned} +# x + y & = 1\\ +# y^2 & = y\\ +# xy & = 0\\ +# -y + y^2 - x*y & = 0 +# y^2 - 2y + 1 & = x^2 +# \end{aligned} +# ``` + +ν4 = moment_matrix(model4[:c]) +SumOfSquares.MultivariateMoments.compute_support!(ν4, FixedRank(3)) + +# This system can be reduced to the equivalent system +# ```math +# \begin{aligned} +# x + y & = 1\\ +# y^2 & = y +# \end{aligned} +# ``` +# which has the solutions $(0, 1)$ and $(1, 0)$. + +SemialgebraicSets.compute_gröbner_basis!(ideal(ν4.support)) +ν4.support +@test length(ν4.support.I.p) == 2 #src + +# The solutions of this system then give the minimizers + +@test length(collect(ν4.support)) == 2 #src +collect(ν4.support) + +# The function `atomic_measure` then reuses the matrix of moments to find the weights $1/2$, $1/2$ corresponding to the diracs centered respectively at $(0, 1)$ and $(1, 0)$. +# This details how the function obtained the result +# $$0.5 \delta(x-1, y) + 0.5 \delta(x, y-1)$$ +# given in the previous section. + +# ## HomotopyContinuation + +# As discussed in the previous section, the atom extraction relies on the solution +# of a system of algebraic equations. The `atomic_measure` function takes an optional +# `algebraic_solver` argument that is used to solve this system of equation. +# If no solver is provided, the default solver of SemialgebraicSets.jl is used which +# currently computes the Gröbner basis, then the multiplication matrices and +# then the Schur decomposition of a random combination of these matrices. +# As the system of equations is obtained from a numerical solution and is represented +# using floating point coefficients, homotopy continuation is recommended as it is +# more numerically robust than Gröbner basis computation. +# The following uses homotopy continuation to solve the system of equations. + +using HomotopyContinuation +algebraic_solver = SemialgebraicSetsHCSolver(; excess_residual_tol = 1e-1, real_tol = 1e-1, compile = false) +atoms4 = atomic_measure(ν4, FixedRank(3), Echelon(), algebraic_solver) #src +@test length(atoms4.atoms) == 2 #src +@test atoms4.atoms[1].weight + atoms4.atoms[2].weight ≈ 1.0 rtol=1e-1 #src +@test atoms4.atoms[1].center[2:-1:1] ≈ atoms4.atoms[2].center[1:2] rtol=1e-1 #src +atomic_measure(ν4, FixedRank(3), Echelon(), algebraic_solver) + +# As the system has 3 equations for 2 variables and the coefficients of the equations +# are to be treated with tolerance since they originate from the solution of an SDP, +# we need to set `excess_residual_tol` and `real_tol` to a high tolerance otherwise, +# HomotopyContinuation would consider that there is no solution. +# Indeed, as the system is overdetermined (it has more equations than variables) +# HomotopyContinuation expects to have excess solution hence it filters out +# excess solution among the solution found. It determines which solution are in excess +# by comparing the infinity norm of the residuals of the equations at the solution with `excess_residual_tol`. +# It also filters out solution for which the absolute value of the imaginary part of one of the entry +# is larger than `real_tol` and strips out the imaginary part. +# The raw solutions obtained by HomotopyContinuation can be obtained as follows: + +F = HomotopyContinuation.System(ν4.support) +res = HomotopyContinuation.solve(F, algebraic_solver.options...) +r = path_results(res) #src +@test length(r) == 4 #src +@test all(HomotopyContinuation.is_excess_solution, r) #src +path_results(res) + +# The printed `residual` above shows why `1e-1` allows to filter how the 2 actual +# solutions from the 2 excess solutions. diff --git a/previews/PR347/tutorials/Polynomial Optimization/qcqp.jl b/previews/PR347/tutorials/Polynomial Optimization/qcqp.jl new file mode 100644 index 000000000..1bc5645d7 --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/qcqp.jl @@ -0,0 +1,78 @@ +# # Nonconvex quadratically constrained quadratic programs + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/nonconvex_qcqp.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/nonconvex_qcqp.ipynb) +# **Adapted from**: [Hesse1973](@cite), [Floudas1999; Section 3.4](@cite), [Laurent2008; Example 6.22](@cite) and [Lasserre2009; Table 5.1](@cite) + +# We consider the nonconvex Quadratically Constrained Quadratic Programs (QCQP) +# introduced in [H73]. +# Consider now the polynomial optimization problem [Laurent2008; Example 6.22](@cite) of +# maximizing the convex quadratic function +# (hence nonconvex since convex programs should either maximize concave functions +# or minimize convex functions) +# $25(x_1 - 2)^2 + (x_2 - 2)^2 + (x_3 - 1)^2 + (x_4 - 4)^2 + (x_5 - 1)^2 + (x_6 - 4)^2$ +# over the basic semialgebraic set defined by the nonconvex quadratic inequalities +# $(x_3 - 3)^2 + x_4 \ge 4$, +# $(x_5 - 3)^2 + x_6 \ge 4$, +# and linear inequalities +# $x_1 - 3x_2 \le 2$, +# $-x_1 + x_2 \le 2$, +# $2 \le x_1 + x_2 \le 6$, +# $0 \le x_1, x_2$, +# $1 \le x_3 \le 5$, +# $0 \le x_4 \le 6$, +# $1 \le x_5 \le 5$, +# $0 \le x_6 \le 10$, +# $x_2 \le 4x_1^4 - 32x_1^3 + 88x_1^2 - 96x_1 + 36$ and the box constraints +# $0 \le x_1 \le 3$ and $0 \le x_2 \le 4$, + +using Test #src +using DynamicPolynomials +@polyvar x[1:6] +centers = [2, 2, 1, 4, 1, 4] +weights = [25, 1, 1, 1, 1, 1] +p = -weights' * (x .- centers).^2 +using SumOfSquares +K = @set x[1] >= 0 && x[2] >= 0 && + x[3] >= 1 && x[3] <= 5 && + x[4] >= 0 && x[4] <= 6 && + x[5] >= 1 && x[5] <= 5 && + x[6] >= 0 && x[6] <= 10 && + (x[3] - 3)^2 + x[4] >= 4 && + (x[5] - 3)^2 + x[6] >= 4 && + x[1] - 3x[2] <= 2 && + -x[1] + x[2] <= 2 && + x[1] + x[2] <= 6 && + x[1] + x[2] >= 2 + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import Clarabel +solver = Clarabel.Optimizer + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`. + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +# The first level of the hierarchy cannot find any lower bound. + +model2 = solve(2) +nothing # hide +@test termination_status(model2) == MOI.INFEASIBLE #src + +# The second level of the hierarchy finds the lower bound of `-310`. + +model3 = solve(4) +nothing # hide +@test termination_status(model3) == MOI.OPTIMAL #src +@test objective_value(model3) ≈ -310 rtol=1e-4 #src diff --git a/previews/PR347/tutorials/Polynomial Optimization/qp.jl b/previews/PR347/tutorials/Polynomial Optimization/qp.jl new file mode 100644 index 000000000..f0154d5fa --- /dev/null +++ b/previews/PR347/tutorials/Polynomial Optimization/qp.jl @@ -0,0 +1,67 @@ +# # Nonconvex QP + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Polynomial Optimization/qp.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Polynomial Optimization/qp.ipynb) +# **Adapted from**: of [Floudas1999; Section 2.2](@cite), [Lasserre2009; Table 5.1](@cite) + +# ## Introduction + +# Consider the nonconvex Quadratic Program (QP) from [Floudas1999; Section 2.2](@cite) +# that minimizes the *concave* function $c^\top x - x^\top Qx / 2$ +# over the polyhedron obtained by intersecting the hypercube $[0, 1]^5$ +# with the halfspace $10x_1 + 12x_2 + 11x_3 + 7x_4 + 4x_5 \le 40$. + +using Test #src + +using LinearAlgebra +c = [42, 44, 45, 47, 47.5] +Q = 100I + +using DynamicPolynomials +@polyvar x[1:5] +p = c'x - x' * Q * x / 2 +using SumOfSquares +K = @set x[1] >= 0 && x[1] <= 1 && + x[2] >= 0 && x[2] <= 1 && + x[3] >= 0 && x[3] <= 1 && + x[4] >= 0 && x[4] <= 1 && + x[5] >= 0 && x[5] <= 1 && + 10x[1] + 12x[2] + 11x[3] + 7x[4] + 4x[5] <= 40 + +# We will now see how to find the optimal solution using Sum of Squares Programming. +# We first need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import Clarabel +solver = Clarabel.Optimizer + +# A Sum-of-Squares certificate that $p \ge \alpha$ over the domain `S`, ensures that $\alpha$ is a lower bound to the polynomial optimization problem. +# The following function searches for the largest lower bound and finds zero using the `d`th level of the hierarchy`. + +function solve(d) + model = SOSModel(solver) + @variable(model, α) + @objective(model, Max, α) + @constraint(model, c, p >= α, domain = K, maxdegree = d) + optimize!(model) + println(solution_summary(model)) + return model +end + +# The first level of the hierarchy does not give any lower bound: + +model2 = solve(2) +nothing # hide +@test termination_status(model2) == MOI.INFEASIBLE #src + +# Indeed, as the constraints have degree 1 and their multipliers are SOS +# so they have an even degree, with `maxdegree` 2 we can only use degree 0 +# multipliers hence constants. The terms of maximal degree in resulting +# sum will therefore only be in `-x' * Q * x/2` hence it is not SOS whatever +# is the value of the multipliers. Let's try with `maxdegree` 3 so that the +# multipliers can be quadratic. +# This second level is now feasible and gives a lower bound of `-22`. + +model3 = solve(3) +nothing # hide +@test objective_value(model3) ≈ -22 rtol=1e-4 #src +@test termination_status(model3) == MOI.OPTIMAL #src diff --git a/previews/PR347/tutorials/Sparsity/sign_symmetry.jl b/previews/PR347/tutorials/Sparsity/sign_symmetry.jl new file mode 100644 index 000000000..03275a318 --- /dev/null +++ b/previews/PR347/tutorials/Sparsity/sign_symmetry.jl @@ -0,0 +1,45 @@ +# # Sign symmetry + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Sparsity/sign_symmetry.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Sparsity/sign_symmetry.ipynb) +# **Adapted from**: Example 4 of [L09] +# +# [L09] Lofberg, Johan. +# *Pre-and post-processing sum-of-squares programs in practice*. +# IEEE transactions on automatic control 54, no. 5 (2009): 1007-1011. + +using Test #src +using DynamicPolynomials +@polyvar x[1:3] + +# We would like to determine whether the following polynomial is a sum-of-squares. + +poly = 1 + x[1]^4 + x[1] * x[2] + x[2]^4 + x[3]^2 + +# In order to do this, we can solve the following Sum-of-Squares program. + +import CSDP +solver = CSDP.Optimizer +using SumOfSquares +function sos_check(sparsity) + model = Model(solver) + con_ref = @constraint(model, poly in SOSCone(), sparsity = sparsity) + optimize!(model) + @test termination_status(model) == MOI.OPTIMAL #src + println(solution_summary(model)) + return gram_matrix(con_ref) +end + +g = sos_check(Sparsity.NoPattern()) +@test g.basis.monomials == [x[1]^2, x[1] * x[2], x[2]^2, x[1], x[2], x[3], 1] #src +g.basis.monomials + +# As detailed in the Example 4 of [L09], we can exploit the *sign symmetry* of +# the polynomial to decompose the large positive semidefinite matrix into smaller ones. + +g = sos_check(Sparsity.SignSymmetry()) +monos = [sub.basis.monomials for sub in g.blocks] +@test length(monos) == 3 #src +@test [x[1], x[2]] in monos #src +@test [x[3]] in monos #src +@test [x[1]^2, x[1] * x[2], x[2]^2, 1] in monos #src diff --git a/previews/PR347/tutorials/Sparsity/term_sparsity.jl b/previews/PR347/tutorials/Sparsity/term_sparsity.jl new file mode 100644 index 000000000..e880dc6d0 --- /dev/null +++ b/previews/PR347/tutorials/Sparsity/term_sparsity.jl @@ -0,0 +1,76 @@ +# # Term sparsity + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Sparsity/term_sparsity.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Sparsity/term_sparsity.ipynb) +# **Adapted from**: Example 3.5 of [WML20b] +# +# [WML20a] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. +# *TSSOS: A Moment-SOS hierarchy that exploits term sparsity*. +# arXiv preprint arXiv:1912.08899 (2020). +# +# [WML20b] Wang, Jie, Victor Magron, and Jean-Bernard Lasserre. +# *Chordal-TSSOS: a moment-SOS hierarchy that exploits term sparsity with chordal extension*. +# arXiv preprint arXiv:2003.03210 (2020). + +using Test #src +using DynamicPolynomials +@polyvar x[1:3] + +# We would like to find the minimum value of the polynomial + +poly = x[1]^2 - 2x[1]*x[2] + 3x[2]^2 - 2x[1]^2*x[2] + 2x[1]^2*x[2]^2 - 2x[2]*x[3] + 6x[3]^2 + 18x[2]^2*x[3] - 54x[2]*x[3]^2 + 142x[2]^2*x[3]^2 + +# The minimum value of the polynomial can be found to be zero. + +import CSDP +solver = CSDP.Optimizer +using SumOfSquares +function sos_min(sparsity) + model = Model(solver) + @variable(model, t) + @objective(model, Max, t) + con_ref = @constraint(model, poly - t in SOSCone(), sparsity = sparsity) + optimize!(model) + return value(t), moment_matrix(con_ref) +end + +bound, ν = sos_min(Sparsity.NoPattern()) +@test bound ≈ 0 atol=1e-6 #src +bound + +# We find the corresponding minimizer `(0, 0, 0)` by matching the moments +# of the moment matrix with a dirac measure centered at this minimizer. + +atomic_measure(ν, 1e-6) + +# We can see below that the basis contained 6 monomials hence we needed to use 6x6 PSD matrix variables. + +@test ν.basis.monomials == [x[1]*x[2], x[2]*x[3], x[1], x[2], x[3], 1] #src +ν.basis + +# Using the monomial/term sparsity method of [WML20a] based on cluster completion, we find the same bound. + +bound, ν = sos_min(Sparsity.Monomial()) +@test bound ≈ 0 atol=1e-6 #src +bound + +# Which is not suprising as no sparsity reduction could be performed. + +@test length(ν.blocks) == 1 #src +@test ν.blocks[1].basis.monomials == [x[1]*x[2], x[2]*x[3], x[1], x[2], x[3], 1] #src +[sub.basis for sub in ν.blocks] + +# Using the monomial/term sparsity method of [WML20b] based on chordal completion, the lower bound is smaller than 0. + +bound, ν = sos_min(Sparsity.Monomial(ChordalCompletion())) +@test bound ≈ -0.00355 rtol=1e-3 #src +bound + +# However, this bound was obtained with an SDP with 4 matrices of size 3x3. + +@test length(ν.blocks) == 4 #src +@test ν.blocks[1].basis.monomials == [x[2], x[1], x[1]*x[2]] #src +@test ν.blocks[2].basis.monomials == [x[2], x[2]*x[3], x[1]*x[2]] #src +@test ν.blocks[3].basis.monomials == [x[3], x[2], x[2]*x[3]] #src +@test ν.blocks[4].basis.monomials == [1, x[2]*x[3], x[1]*x[2]] #src +[sub.basis for sub in ν.blocks] diff --git a/previews/PR347/tutorials/Symmetry/cyclic.jl b/previews/PR347/tutorials/Symmetry/cyclic.jl new file mode 100644 index 000000000..f7088f4b0 --- /dev/null +++ b/previews/PR347/tutorials/Symmetry/cyclic.jl @@ -0,0 +1,178 @@ +# # Cyclic symmetry for Sums of Hermitian Squares + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Symmetry/cyclic.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Symmetry/cyclic.ipynb) + +using Test #src + +# We start by defining the Cyclic group. + +using GroupsCore +import PermutationGroups + +struct CyclicElem <: GroupElement + n::Int + id::Int +end +Base.:(==)(a::CyclicElem, b::CyclicElem) = a.n == b.n && a.id == b.id +Base.inv(el::CyclicElem) = CyclicElem(el.n, (el.n - el.id) % el.n) + +function Base.:*(a::CyclicElem, b::CyclicElem) + return CyclicElem(a.n, (a.id + b.id) % a.n) +end +Base.:^(el::CyclicElem, k::Integer) = CyclicElem(el.n, (el.id * k) % el.n) + +Base.conj(a::CyclicElem, b::CyclicElem) = inv(b) * a * b +Base.:^(a::CyclicElem, b::CyclicElem) = conj(a, b) + +function PermutationGroups.order(el::CyclicElem) + return div(el.n, gcd(el.n, el.id)) +end + +struct CyclicGroup <: Group + n::Int +end +Base.eltype(::CyclicGroup) = CyclicElem +Base.one(c::Union{CyclicGroup, CyclicElem}) = CyclicElem(c.n, 0) +PermutationGroups.gens(c::CyclicGroup) = [CyclicElem(c.n, 1)] +PermutationGroups.order(::Type{T}, c::CyclicGroup) where {T} = convert(T, c.n) +function Base.iterate(c::CyclicGroup, prev::CyclicElem=CyclicElem(c.n, -1)) + id = prev.id + 1 + if id >= c.n + return nothing + else + next = CyclicElem(c.n, id) + return next, next + end +end + +# Now we define that the cyclic group acts on monomial by permuting variables +# cyclically. So for instance, `CyclicElem(3, 1)` would transform +# `x_1^3*x_2*x_3^4` into `x_1^4*x_2^3*x_3`. + +import MultivariatePolynomials as MP + +using SumOfSquares + +struct Action{V<:MP.AbstractVariable} <: Symmetry.OnMonomials + variables::Vector{V} +end +Symmetry.SymbolicWedderburn.coeff_type(::Action) = Float64 +function Symmetry.SymbolicWedderburn.action(a::Action, el::CyclicElem, mono::MP.AbstractMonomial) + return prod(MP.powers(mono), init=MP.constant_monomial(mono)) do (var, exp) + index = findfirst(isequal(var), a.variables) + new_index = mod1(index + el.id, el.n) + return a.variables[new_index]^exp + end +end + +using DynamicPolynomials +@polyvar x[1:3] +action = Action(x) +g = CyclicElem(3, 1) +@test Symmetry.SymbolicWedderburn.action(action, g, x[1]^3 * x[2] * x[3]^4) == x[1]^4 * x[2]^3 * x[3] #src +Symmetry.SymbolicWedderburn.action(action, g, x[1]^3 * x[2] * x[3]^4) + +# The following polynomial `poly` is invariant under the action of the group `G`. + +N = 3 +G = CyclicGroup(N) +poly = sum(x[i] * x[mod1(i + 1, N)] for i in 1:N) + sum(x.^2) +@test Symmetry.SymbolicWedderburn.action(action, g, poly) == poly #src +Symmetry.SymbolicWedderburn.action(action, g, poly) + +# Let's now find the minimum of `p` by exploiting this symmetry. + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, action) +con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) +optimize!(model) +@test termination_status(model) == MOI.OPTIMAL #src +@test objective_value(model) ≈ 0.0 atol=1e-4 #src +solution_summary(model) + +# Let's look at the symmetry adapted basis used. + +gram = gram_matrix(con_ref).blocks #src +@test length(gram) == 3 #src +@test gram[1].Q ≈ [0 0; 0 2] #src +@test length(gram[1].basis.polynomials) == 2 #src +@test gram[1].basis.polynomials[1] == 1 #src +@test gram[1].basis.polynomials[2] ≈ -sum(x)/√3 #src +@test gram[2].Q ≈ [0.5;;] #src +@test length(gram[2].basis.polynomials) == 1 #src +@test gram[2].basis.polynomials[1] ≈ (x[1] + x[2] - 2x[3])/√6 #src +@test gram[3].Q == gram[2].Q #src +@test length(gram[3].basis.polynomials) == 1 #src +@test gram[3].basis.polynomials[1] ≈ (x[1] - x[2])/√2 #src +for gram in gram_matrix(con_ref).blocks + println(gram.basis.polynomials) + display(gram.Q) +end + +# Let's look into more details at the last two elements of the basis. + +basis = [(x[1] + x[2] - 2x[3])/√6, (x[1] - x[2])/√2] + +# This actually constitutes the basis for an invariant subspace corresponding +# to a group character of degree 2 and multiplicity 1. +# This means that it decomposes the semidefinite matrix into 2 blocks of size +# 1-by-1 that are equal. Indeed, we see above that `gram.Q` is identically equal for both. +# As the group is generated by one element `g`, we can just verify it by verifying +# its invariance under `g`. +# The image of each element under the basis is: + +image = [Symmetry.SymbolicWedderburn.action(action, g, p) for p in basis] + +# We can see that they are both still in the same 2-dimensional subspace. + +a = -1/2 +b = √3/2 +@test all(image .≈ [a -b; b a] * basis) #src +[a -b; b a] * basis + +# In fact, these last two basis comes from the real decomposition of a complex one. + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, action) +cone = SumOfSquares.NonnegPolyInnerCone{MOI.HermitianPositiveSemidefiniteConeTriangle}() +con_ref = @constraint(model, poly - t in cone, symmetry = pattern) +optimize!(model) +@test termination_status(model) == MOI.OPTIMAL #src +@test objective_value(model) ≈ 0.0 atol=1e-4 #src +solution_summary(model) + +gram = gram_matrix(con_ref).blocks #src +@test length(gram) == 3 #src +@test gram[1].Q ≈ [0 0; 0 2] #src +@test length(gram[1].basis.polynomials) == 2 #src +@test gram[1].basis.polynomials[1] == 1 #src +@test gram[1].basis.polynomials[2] ≈ -sum(x)/√3 #src +@test gram[2].Q ≈ [0.5;;] rtol = 1e-6 #src +@test length(gram[2].basis.polynomials) == 1 #src +@test gram[2].basis.polynomials[1] ≈ (basis[1] - basis[2] * im) / √2 #src +@test gram[3].Q ≈ [0.5;;] rtol = 1e-6 #src +@test length(gram[3].basis.polynomials) == 1 #src +@test gram[3].basis.polynomials[1] ≈ (basis[1] + basis[2] * im) / √2 #src +for gram in gram_matrix(con_ref).blocks + println(gram.basis.polynomials) + display(gram.Q) +end + +# We can see that the real invariant subspace was in fact coming from two complex conjugate complex invariant subspaces: + +complex_basis = basis[1] + im * basis[2] +image = Symmetry.SymbolicWedderburn.action(action, g, complex_basis) + +# And there is a direct correspondance between the representation of the real and complex versions: + +@test all(image .≈ (a + b * im) * complex_basis) #src +(a + b * im) * complex_basis diff --git a/previews/PR347/tutorials/Symmetry/dihedral.jl b/previews/PR347/tutorials/Symmetry/dihedral.jl new file mode 100644 index 000000000..7802a8b65 --- /dev/null +++ b/previews/PR347/tutorials/Symmetry/dihedral.jl @@ -0,0 +1,185 @@ +# # Dihedral symmetry of the Robinson form + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Symmetry/dihedral_symmetry_of_the_robinson_form.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Symmetry/dihedral_symmetry_of_the_robinson_form.ipynb) +# **Adapted from**: Example 5.4 of [GP04] +# +# [GP04] Gatermann, Karin and Parrilo, Pablo A. +# *Symmetry groups, semidefinite programs, and sums of squares*. +# Journal of Pure and Applied Algebra 192.1-3 (2004): 95-128. + + +using Test #src +import Random #src +Random.seed!(0) #src + +# We start by defining the Dihedral group of order 8. +# This group is isomorphic to the following permutation group: + +using PermutationGroups +d = perm"(1, 2, 3, 4)" +c = perm"(1, 3)" +G = PermGroup([c, d]) + +# We could rely on this isomorphism to define this group. +# However, in order to illustrate how to do symmetry reduction with a custom group, +# we show in this example what should be implemented to define a new group. + +import GroupsCore + +struct DihedralGroup <: GroupsCore.Group + n::Int +end + +struct DihedralElement <: GroupsCore.GroupElement + n::Int + reflection::Bool + id::Int +end + +# Implementing GroupsCore API: + +Base.one(G::DihedralGroup) = DihedralElement(G.n, false, 0) + +Base.eltype(::Type{DihedralGroup}) = DihedralElement +Base.IteratorSize(::Type{DihedralGroup}) = Base.HasLength() + +function Base.iterate(G::DihedralGroup, prev::DihedralElement=DihedralElement(G.n, false, -1)) + if prev.id + 1 >= G.n + if prev.reflection + return nothing + else + next = DihedralElement(G.n, true, 0) + end + else + next = DihedralElement(G.n, prev.reflection, prev.id + 1) + end + return next, next +end + +GroupsCore.order(::Type{T}, G::DihedralGroup) where {T} = convert(T, 2G.n) +GroupsCore.gens(G::DihedralGroup) = [DihedralElement(G.n, false, 1), DihedralElement(G.n, true, 0)] + +# Base.rand not needed for our purposes here + +Base.parent(g::DihedralElement) = DihedralGroup(g.n) +function Base.:(==)(g::DihedralElement, h::DihedralElement) + return g.n == h.n && g.reflection == h.reflection && g.id == h.id +end + +function Base.inv(el::DihedralElement) + if el.reflection || iszero(el.id) + return el + else + return DihedralElement(el.n, false, el.n - el.id) + end +end +function Base.:*(a::DihedralElement, b::DihedralElement) + a.n == b.n || error("Cannot multiply elements from different Dihedral groups") + id = mod(a.reflection ? a.id - b.id : a.id + b.id, a.n) + return DihedralElement(a.n, a.reflection != b.reflection, id) +end + +Base.copy(a::DihedralElement) = DihedralElement(a.n, a.reflection, a.id) + +# optional functions: +function GroupsCore.order(el::DihedralElement) + if el.reflection + return 2 + else + if iszero(el.id) + return 1 + else + return div(el.n, gcd(el.n, el.id)) + end + end +end + +# The Robinson form is invariant under the following action of the Dihedral group on monomials: +# The action of each element of the groups is to map the variables `x, y` to: +# +# | id | rotation | reflection | +# |----|----------|------------| +# | 0 | x, y | y, x | +# | 1 | -y, x | -x, y | +# | 2 | -x, -y | -y, -x | +# | 3 | y, -x | x, -y | + +using SumOfSquares +using DynamicPolynomials +@polyvar x y +struct DihedralAction <: Symmetry.OnMonomials end +import SymbolicWedderburn +SymbolicWedderburn.coeff_type(::DihedralAction) = Float64 +function SymbolicWedderburn.action(::DihedralAction, el::DihedralElement, mono::AbstractMonomial) + if iseven(el.reflection + el.id) + var_x, var_y = x, y + else + var_x, var_y = y, x + end + sign_x = 1 <= el.id <= 2 ? -1 : 1 + sign_y = 2 <= el.id ? -1 : 1 + return mono([x, y] => [sign_x * var_x, sign_y * var_y]) +end + +poly = x^6 + y^6 - x^4 * y^2 - y^4 * x^2 - x^4 - y^4 - x^2 - y^2 + 3x^2 * y^2 + 1 + +# We can verify that `poly` is indeed invariant under the action of each element of the group as follows. + +G = DihedralGroup(4) +for g in G + @show SymbolicWedderburn.action(DihedralAction(), g, poly) + @test SymbolicWedderburn.action(DihedralAction(), g, poly) == poly #src +end + +# We can exploit this symmetry for reducing the problem using the `SymmetricIdeal` certificate as follows: + +import CSDP +function solve(G) + solver = CSDP.Optimizer + model = Model(solver) + @variable(model, t) + @objective(model, Max, t) + pattern = Symmetry.Pattern(G, DihedralAction()) + con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) + optimize!(model) + @test value(t) ≈ -3825/4096 rtol=1e-2 #src + @show value(t) + + + g = gram_matrix(con_ref).blocks #src + @test length(g) == 5 #src + @test g[1].basis.polynomials == [y^3, x^2*y, y] #src + @test g[2].basis.polynomials == [-x^3, -x*y^2, -x] #src + for i in 1:2 #src + I = 3:-1:1 #src + Q = g[i].Q[I, I] #src + @test size(Q) == (3, 3) #src + @test Q[2, 2] ≈ 1 rtol=1e-2 #src + @test Q[1, 2] ≈ 5/8 rtol=1e-2 #src + @test Q[2, 3] ≈ -1 rtol=1e-2 #src + @test Q[1, 1] ≈ 25/64 rtol=1e-2 #src + @test Q[1, 3] ≈ -5/8 rtol=1e-2 #src + @test Q[3, 3] ≈ 1 rtol=1e-2 #src + end #src + @test length(g[3].basis.polynomials) == 2 #src + @test g[3].basis.polynomials[1] == 1.0 #src + @test g[3].basis.polynomials[2] ≈ -(√2/2)x^2 - (√2/2)y^2 #src + @test size(g[3].Q) == (2, 2) #src + @test g[3].Q[1, 1] ≈ 7921/4096 rtol=1e-2 #src + @test g[3].Q[1, 2] ≈ 0.983 rtol=1e-2 #src + @test g[3].Q[2, 2] ≈ 1/2 rtol=1e-2 #src + @test g[4].basis.polynomials == [x * y] #src + @test size(g[4].Q) == (1, 1) #src + @test g[4].Q[1, 1] ≈ 0 atol=1e-2 #src + @test length(g[5].basis.polynomials) == 1 #src + @test g[5].basis.polynomials[1] ≈ (√2/2)x^2 - (√2/2)y^2 #src + @test size(g[5].Q) == (1, 1) #src + @test g[5].Q[1, 1] ≈ 0 atol=1e-2 #src + for g in gram_matrix(con_ref).blocks + println(g.basis.polynomials) + end +end +solve(G) + +# We notice that we indeed find `-3825/4096` and that symmetry was exploited. diff --git a/previews/PR347/tutorials/Symmetry/even_reduction.jl b/previews/PR347/tutorials/Symmetry/even_reduction.jl new file mode 100644 index 000000000..22a3b2b37 --- /dev/null +++ b/previews/PR347/tutorials/Symmetry/even_reduction.jl @@ -0,0 +1,50 @@ +# # Even reduction + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Symmetry/even_reduction.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Symmetry/even_reduction.ipynb) + +using Test #src +using DynamicPolynomials +@polyvar x + +# We would like to find the minimum value of the following polynomial: + +poly = x^4 - 2x^2 + +using SumOfSquares + +# We define the custom action as follows: + +struct OnSign <: Symmetry.OnMonomials end +using PermutationGroups +import SymbolicWedderburn +SymbolicWedderburn.coeff_type(::OnSign) = Float64 +function SymbolicWedderburn.action(::OnSign, p::Permutation, mono::AbstractMonomial) + if isone(p) || iseven(DynamicPolynomials.degree(mono)) + return 1 * mono + else + @assert p.perm == perm"(1,2)" + return -1 * mono + end +end +G = PermGroup([perm"(1,2)"]) + +# We can exploit the symmetry as follows: + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, OnSign()) +con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) +optimize!(model) +@test value(t) ≈ -1 #src +value(t) + +# We indeed find `-1`, let's verify that symmetry was exploited: + +@test length(gram_matrix(con_ref).blocks) == 2 #src +@test gram_matrix(con_ref).blocks[1].basis.polynomials == [1, x^2] #src +@test gram_matrix(con_ref).blocks[2].basis.polynomials == [x] #src +gram_matrix(con_ref) diff --git a/previews/PR347/tutorials/Symmetry/permutation_symmetry.jl b/previews/PR347/tutorials/Symmetry/permutation_symmetry.jl new file mode 100644 index 000000000..a24ecec24 --- /dev/null +++ b/previews/PR347/tutorials/Symmetry/permutation_symmetry.jl @@ -0,0 +1,69 @@ +# # Symmetry reduction + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Symmetry/symmetry_reduction.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Symmetry/symmetry_reduction.ipynb) +# **Adapted from**: [SymbolicWedderburn example](https://github.com/kalmarek/SymbolicWedderburn.jl/blob/tw/ex_sos/examples/ex_C4.jl) + +import MutableArithmetics as MA +using MultivariatePolynomials +using MultivariateBases + +using Test #src +using DynamicPolynomials +@polyvar x[1:4] + +# We would like to find the minimum value of the polynomial + +poly = sum(x) + sum(x.^2) + +# As we can decouple the problem for each `x[i]` for which `x[i] + x[i]^2` has +# minimum value 0.25, we would expect to get `-1` as answer. +# Can this decoupling be exploited by SumOfSquares as well ? +# For this, we need to use a certificate that can exploit the permutation symmetry of the polynomial. + +using SumOfSquares + +# We define the symmetry group as a permutation group in the variables. +# In order to do that, we define the action of a permutation on a monomial +# as the monomial obtained after permuting the variables. + +using PermutationGroups +G = PermGroup([perm"(1,2,3,4)"]) + +# We can use this certificate as follows: + +import CSDP +solver = CSDP.Optimizer +model = Model(solver) +@variable(model, t) +@objective(model, Max, t) +pattern = Symmetry.Pattern(G, Symmetry.VariablePermutation()) +con_ref = @constraint(model, poly - t in SOSCone(), symmetry = pattern) +optimize!(model) +@test value(t) ≈ -1 rtol=1e-6 #src +value(t) + +# We indeed find `-1`, let's verify that symmetry was exploited: + +g = gram_matrix(con_ref).blocks #src +@test length(g) == 4 #src +@test length(g[1].basis.polynomials) == 2 #src +@test g[1].basis.polynomials[1] == 1.0 #src +@test g[1].basis.polynomials[2] ≈ -0.5 * sum(x) #src +@test size(g[1].Q) == (2, 2) #src +@test g[1].Q[1, 1] ≈ 1.0 atol=1e-6 #src +@test g[1].Q[1, 2] ≈ -1.0 atol=1e-6 #src +@test g[1].Q[2, 2] ≈ 1.0 atol=1e-6 #src +@test length(g[2].basis.polynomials) == 1 #src +@test g[2].basis.polynomials[1] ≈ (x[2] - x[4]) / √2 #src +@test size(g[2].Q) == (1, 1) #src +@test g[2].Q[1, 1] ≈ 1.0 atol=1e-6 #src +@test length(g[3].basis.polynomials) == 1 #src +@test g[3].basis.polynomials[1] ≈ (x[1] - x[3]) / √2 #src +@test size(g[3].Q) == (1, 1) #src +@test g[3].Q[1, 1] ≈ 1.0 atol=1e-6 #src +@test length(g[4].basis.polynomials) == 1 #src +@test g[4].basis.polynomials[1] ≈ (x[1] - x[2] + x[3] - x[4]) / 2 #src +@test size(g[4].Q) == (1, 1) #src +@test g[4].Q[1, 1] ≈ 1.0 atol=1e-6 #src +gram_matrix(con_ref).blocks diff --git a/previews/PR347/tutorials/Systems and Control/barrier_certificate.jl b/previews/PR347/tutorials/Systems and Control/barrier_certificate.jl new file mode 100644 index 000000000..4f174da9a --- /dev/null +++ b/previews/PR347/tutorials/Systems and Control/barrier_certificate.jl @@ -0,0 +1,80 @@ +# # Barrier certificates for collision avoidance + +# **Adapted from**: Example 2 of "Engineering applications of SOS polynomials" by Georgina Hall, from +# the 2019 AMS Short Course on Sum of Squares: Theory and Applications +# Implementation by: Hugo Tadashi Kussaba + +using Test #src +using DynamicPolynomials +@polyvar x[1:2] + +using SumOfSquares +using CSDP + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints. +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +# We define below the vector field ``\text{d}x/\text{d}t = f`` + +f = [ x[2], + -x[1] + (1/3)*x[1]^3 - x[2]] + +# Semi-algebraic function describing the unsafe set 𝒳ᵤ +g₁ = -(x[1]+1)^2 - (x[2]+1)^2 + 0.16 # 𝒳ᵤ = {x ∈ R²: g₁(x) ≥ 0} +# Semi-algebraic function describing the initial set 𝒳₀ +h₁ = -(x[1]-1.5)^2 - x[2]^2 + 0.25 # 𝒳₀ = {x ∈ R²: h₁(x) ≥ 0} + +# Define SOS barrier function B +monos = monomials(x, 0:4) +@variable(model, B, Poly(monos)) + +# Define barrier certificate constraints using SOS relaxation + +# B(x) > 0 for all x ∈ 𝒳ᵤ +ε = 0.001 +@constraint(model, B >= ε, domain = @set(g₁ >= 0)) + +# B(x) ≤ 0 for all x ∈ 𝒳₀ +@constraint(model, B <= 0, domain = @set(h₁ >= 0)) + +# Ḃ(x) ≤ 0 for all x ∈ R² +using LinearAlgebra # Needed for `dot` +dBdt = dot(differentiate(B, x), f) +@constraint(model, -dBdt >= 0) + +# The model is ready to be optimized by the solver: +JuMP.optimize!(model) + +# We verify that the solver has found a feasible solution: +JuMP.primal_status(model) +@test JuMP.primal_status(model) == MOI.FEASIBLE_POINT #src + +# Plot the phase plot with the 0-level set of the barrier function, and the boundary of the initial and unsafe sets +import DifferentialEquations, Plots, ImplicitPlots +function phase_plot(f, B, g₁, h₁, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5()) + X₀plot = ImplicitPlots.implicit_plot(h₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="X₀", linecolor=:blue) + Xᵤplot = ImplicitPlots.implicit_plot!(g₁; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="Xᵤ", linecolor=:teal) + Bplot = ImplicitPlots.implicit_plot!(B; xlims=(-2, 3), ylims=(-2.5, 2.5), resolution = 1000, label="B = 0", linecolor=:red) + Plots.plot(X₀plot) + Plots.plot!(Xᵤplot) + Plots.plot!(Bplot) + ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f] + ∇pt(v, p, t) = ∇(v[1], v[2]) + function traj(v0) + tspan = (0.0, Δt) + prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan) + return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8) + end + ticks = -5:0.5:5 + X = repeat(ticks, 1, length(ticks)) + Y = X' + Plots.quiver!(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5) + for x0 in X0 + Plots.plot!(traj(x0), vars=(1, 2), label = nothing) + end + Plots.plot!(xlims = (-2, 3), ylims = (-2.5, 2.5)) +end + +phase_plot(f, value(B), g₁, h₁, 10, 30.0, [[x1, x2] for x1 in 1.2:0.2:1.7, x2 in -0.35:0.1:0.35]) diff --git a/previews/PR347/tutorials/Systems and Control/julia_set.jl b/previews/PR347/tutorials/Systems and Control/julia_set.jl new file mode 100644 index 000000000..4ddc86402 --- /dev/null +++ b/previews/PR347/tutorials/Systems and Control/julia_set.jl @@ -0,0 +1,150 @@ +# # Outer approximation of Julia set + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Systems and Control/julia_set.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Systems and Control/julia_set.ipynb) +# **Adapted from**: Section 7.1.3 of [KHJ14] +# +# [KHJ14] Milan Korda, Didier Henrion, and Colin N. Jones. +# *Convex computation of the maximum controlled invariant set for polynomial control systems*. +# SIAM Journal on Control and Optimization 52.5 (2014): 2944-2969. + +# The Julia map is defined as follows: + +using Test #src +function julia_map(point, c) + a, b = point + return [a^2 - b^2 + real(c), 2a * b + imag(c)] +end + + +# The *escape radius" is the radius `r` such that `r^2 ≥ r + abs(c)`. +# Ouside of the circle of that radius, all points diverge so we know the Julia set belongs to that circle. + +escape_radius(c) = (1 + √(1 + 4 * abs(c))) / 2 + +# To check whether a point is in the Julia set, we can iterate and once the point leaves the circle of escape radius, +# we consider that it is not in the Julia set, if it stays in the set, we consider that it is in the Julia set. +# This gives an outer approximation that converges to the Julia set when `m` increases. + +using LinearAlgebra +function in_set(x, c, m=2000) + r = escape_radius(c) + for i in 1:m + if norm(x) > r + return false + end + x = julia_map(x, c) + end + return true +end + +# To sort of minimize a level set of a polynomial we minimize integral of that polynomial. +# We borrow the following from https://doi.org/10.1080/00029890.2001.11919774 + +using SpecialFunctions +using DynamicPolynomials +β(α) = (α + 1) / 2 +function circle_integral(mono::AbstractMonomial) + if any(isodd, exponents(mono)) + return 0.0 + else + return 2 * prod(gamma ∘ β, exponents(mono)) / gamma(sum(β, exponents(mono))) + end +end +function disk_integral(mono::AbstractMonomial, r) + d = degree(mono) + nvariables(mono) + return circle_integral(mono) * r^d / d +end +function disk_integral(p::AbstractPolynomialLike, r) + return sum(MultivariatePolynomials.coefficient(t) * disk_integral(monomial(t), r) for t in terms(p)) +end + +# The following function implements [KHJ14, (8)]. + +using SumOfSquares +function outer_approximation(solver, d::Int, c; α = 1/2) + @polyvar x[1:2] + model = SOSModel(solver) + r = escape_radius(c) + S = @set sum(x.^2) <= r^2 + @variable(model, v, Poly(monomials(x, 0:2d))) + @variable(model, w0, SOSPoly(monomials(x, 0:d))) + @variable(model, w1, SOSPoly(monomials(x, 0:(d - 1)))) + @constraint(model, α * v(x => julia_map(x, c)) <= v, domain = S) + w = w0 + w1 * (r^2 - sum(x.^2)) + @constraint(model, w >= v + 1, domain = S) + @objective(model, Min, disk_integral(w, r)) + optimize!(model) + @test termination_status(model) in [MOI.OPTIMAL, MOI.ALMOST_OPTIMAL] #src + @test primal_status(model) in [MOI.FEASIBLE_POINT, MOI.NEARLY_FEASIBLE_POINT] #src + if primal_status(model) == MOI.NO_SOLUTION + return + end + return model +end + +# The following function plots the Julia set with the outer approximation. + +using ImplicitPlots +using Plots +function julia_plot(poly, c, n=200, m=1000; tol=1e-6, res = 1000) + r = escape_radius(c) + p = implicit_plot(poly; xlims=(-r, r) .* 1.1, ylims=(-r, r), resolution = res, label="") + θ = range(0, stop=2π, length=100) + points = Vector{Float64}[] + as = range(-r, r, length=n) + bs = range(-r, r, length=n) + for a in as, b in bs + point = [a, b] + if in_set(point, c, m) + push!(points, point) + end + end + xs = [point[1] for point in points] + ys = [point[2] for point in points] + scatter!(p, xs, ys, label="", markerstrokewidth=0, markersize=1.5, m=:pixel) + return p +end + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. + +import CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + +# Let's start with the value of `c` corresponding to the left image of [KHJ14, Figure 3] and with degree 2. + +c = -0.7 + 0.2im +model = outer_approximation(solver, 2, c) +solution_summary(model) + +# We visualize below: + +julia_plot(value(model[:v]), c) + +# Let's now look at degree 4. + +model = outer_approximation(solver, 4, c) +solution_summary(model) + +# We visualize below: + +julia_plot(value(model[:v]), c) + +# Let's now use the value of `c` corresponding to the right image of [KHJ14, Figure 3] and with degree 2. + +c = -0.9 + 0.2im +model = outer_approximation(solver, 2, c) +solution_summary(model) + +# We visualize below: + +julia_plot(value(model[:v]), c) + +# Let's now look at degree 4. + +model = outer_approximation(solver, 4, c) +solution_summary(model) + +# We visualize below: + +julia_plot(value(model[:v]), c) diff --git a/previews/PR347/tutorials/Systems and Control/lyapunov_function_search.jl b/previews/PR347/tutorials/Systems and Control/lyapunov_function_search.jl new file mode 100644 index 000000000..024562a4c --- /dev/null +++ b/previews/PR347/tutorials/Systems and Control/lyapunov_function_search.jl @@ -0,0 +1,66 @@ +# # Lyapunov Function Search + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Systems and Control/lyapunov_function_search.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Systems and Control/lyapunov_function_search.ipynb) +# **Adapted from**: SOSTOOLS' SOSDEMO2 (See Section 4.2 of [SOSTOOLS User's Manual](http://sysos.eng.ox.ac.uk/sostools/sostools.pdf)) + +using Test #src +using DynamicPolynomials +@polyvar x[1:3] + +# We define below the vector field ``\text{d}x/\text{d}t = f`` + +f = [-x[1]^3 - x[1] * x[3]^2, + -x[2] - x[1]^2 * x[2], + -x[3] - 3x[3] / (x[3]^2 + 1) + 3x[1]^2 * x[3]] + +# We need to pick an SDP solver, see [here](https://jump.dev/JuMP.jl/v1.12/installation/#Supported-solvers) for a list of the available choices. +# We use `SOSModel` instead of `Model` to be able to use the `>=` syntax for Sum-of-Squares constraints. + +using SumOfSquares +using CSDP +solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) +model = SOSModel(solver); + +# We are searching for a Lyapunov function $V(x)$ with monomials $x_1^2$, $x_2^2$ and $x_3^2$. +# We first define the monomials to be used for the Lyapunov function: + +monos = x.^2 + +# We now define the Lyapunov function as a polynomial decision variable with these monomials: + +@variable(model, V, Poly(monos)) + +# We need to make sure that the Lyapunov function is strictly positive. +# We can do this with a constraint $V(x) \ge \epsilon (x_1^2 + x_2^2 + x_3^2)$, +# let's pick $\epsilon = 1$: + +@constraint(model, V >= sum(x.^2)) + +# We now compute $\text{d}V/\text{d}x \cdot f$. + +using LinearAlgebra # Needed for `dot` +dVdt = dot(differentiate(V, x), f) + +# The denominator is $x[3]^2 + 1$ is strictly positive so the sign of `dVdt` is the +# same as the sign of its numerator. + +P = dVdt.num + +# Hence, we constrain this numerator to be nonnegative: + +@constraint(model, P <= 0) + +# The model is ready to be optimized by the solver: + +JuMP.optimize!(model) + +# We verify that the solver has found a feasible solution: + +JuMP.primal_status(model) +@test JuMP.primal_status(model) == MOI.FEASIBLE_POINT #src + +# We can now obtain this feasible solution with: + +value(V) +@test iszero(remove_monomials(value(V), monos)) #src diff --git a/previews/PR347/tutorials/Systems and Control/stabilization_of_nonlinear_systems.jl b/previews/PR347/tutorials/Systems and Control/stabilization_of_nonlinear_systems.jl new file mode 100644 index 000000000..fdf948912 --- /dev/null +++ b/previews/PR347/tutorials/Systems and Control/stabilization_of_nonlinear_systems.jl @@ -0,0 +1,98 @@ +# # Stabilization of nonlinear systems + +#md # [![](https://mybinder.org/badge_logo.svg)](@__BINDER_ROOT_URL__/generated/Systems and Control/stabilization_of_nonlinear_systems.ipynb) +#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/generated/Systems and Control/stabilization_of_nonlinear_systems.ipynb) +# **Adapted from**: Examples 1, 2 and 3 of [PPA04] +# +# [PPA04] Prajna, Stephen, Pablo A. Parrilo, and Anders Rantzer. +# *Nonlinear control synthesis by convex optimization*. +# IEEE Transactions on Automatic Control 49.2 (2004): 310-314. + +using Test #src +using DynamicPolynomials +@polyvar x[1:2] + +using SumOfSquares +using CSDP +using LinearAlgebra # for ⋅ +using MultivariatePolynomials +divergence(f) = sum(differentiate.(f, x)) +function controller(f, g, b, α, degs) + solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true) + model = SOSModel(solver) + a = 1 + monos = monomials(x, degs) + N = length(monos) + 1 + @variable(model, c[1:N] in MOI.NormOneCone(N)) + c_poly = polynomial(c[2:end], monos) + fagc = f * a + g * c_poly + @constraint(model, b * divergence(fagc) - α * differentiate(b, x) ⋅ fagc in SOSCone()) + @objective(model, Min, c[1]) + optimize!(model) + if termination_status(model) != MOI.OPTIMAL + @warn("Termination status $(termination_status(model)): $(raw_status(model))") + end + u = value(c_poly) / value(a) + return MultivariatePolynomials.map_coefficients(coef -> abs(coef) < 1e-6 ? 0.0 : coef, u) +end + +import DifferentialEquations, Plots +function phase_plot(f, quiver_scaling, Δt, X0, solver = DifferentialEquations.Tsit5()) + ∇(vx, vy) = [fi(x[1] => vx, x[2] => vy) for fi in f] + ∇pt(v, p, t) = ∇(v[1], v[2]) + function traj(v0) + tspan = (0.0, Δt) + prob = DifferentialEquations.ODEProblem(∇pt, v0, tspan) + return DifferentialEquations.solve(prob, solver, reltol=1e-8, abstol=1e-8) + end + ticks = -5:0.5:5 + X = repeat(ticks, 1, length(ticks)) + Y = X' + Plots.quiver(X, Y, quiver = (x, y) -> ∇(x, y) / quiver_scaling, linewidth=0.5) + for x0 in X0 + Plots.plot!(traj(x0), vars=(1, 2), label = nothing) + end + Plots.plot!(xlims = (-5, 5), ylims = (-5, 5)) +end + +# ## Example 1 + +g = [0, 1] +f = [x[2] - x[1]^3 + x[1]^2, 0] +b = 3x[1]^2 + 2x[1]*x[2] + 2x[2]^2 +u = controller(f, g, b, 4, 0:3) +@test monomials(u) == [x[2]^3, x[1], x[2]] #src + +# We find the controller above which gives the following phase plot. + +phase_plot(f + g * u, 200, 10.0, [[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x1 != 0 || x2 != 0]) + +# ## Example 2 + +g = [0, 1] +f = [2x[1]^3 + x[1]^2*x[2] - 6x[1]*x[2]^2 + 5x[2]^3, 0] +b = x[1]^2 + x[2]^2 +u = controller(f, g, b, 2.5, 0:3) +@test monomials(u) == [x[1]^3, x[1]^2*x[2], x[1]*x[2]^2, x[2]^3] #src + +# We find the controller above which gives the following phase plot. + +phase_plot(f + g * u, 2000, 5.0, [[-1.0, -5.0], [1.0, 5.0]]) + +# ## Example 3 + +g = [0, x[2]] +f = [-6x[1]*x[2]^2 - x[1]^2*x[2] + 2x[2]^3, 0] +b = x[1]^2 + x[2]^2 +u = controller(f, g, b, 3, 0:2) +@test monomials(u) == [x[1]^2, x[2]^2] #src + +# We find the controller above which gives the following phase plot. + +X0 = [Float64[x1, x2] for x1 in -5:5:5, x2 in -5:5:5 if x2 != 0] +ε = 1e-4 # We separate the starting point slightly from the hyperplane `x2 = 0` which is invariant. +push!(X0, [-4, ε]) +push!(X0, [-3, -ε]) +push!(X0, [ 3, ε]) +push!(X0, [ 4, -ε]) +phase_plot(f + g * u, 2000, 10.0, X0) diff --git a/previews/PR347/variables/index.html b/previews/PR347/variables/index.html new file mode 100644 index 000000000..3e02e58e9 --- /dev/null +++ b/previews/PR347/variables/index.html @@ -0,0 +1,96 @@ + +Variables · SumOfSquares

Polynomial and Sum-of-Squares variables

Polynomial variables

While JuMP allows to create decision variables representing a number whose value needs to be optimized upon by the optimizer, PolyJuMP allows to create polynomial decision variables. In order to do that, we first need to create polynomial variables with the @polyvar macro:

julia> using DynamicPolynomials # or TypedPolynomials, pick your favorite
+
+julia> @polyvar x y
+(x, y)

Note that these should not be confused with JuMP's decision variables which are created using the @variable macro. The polynomial decision variable that will be created need to be parametrized by a polynomial basis of finite size. For instance, if we want to find a quadratic polynomial, we can parametrize it with all monomials of degree between 0 and 2. Generating a vector with such monomials can be achieved through the monomials function:

julia> X = monomials([x, y], 0:2)
+6-element MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}:
+ 1
+ y
+ x
+ y²
+ xy
+ x²

We can now create our polynomial variable p as follows:

julia> using SumOfSquares
+
+julia> model = Model()
+A JuMP Model
+Feasibility problem with:
+Variables: 0
+Model mode: AUTOMATIC
+CachingOptimizer state: NO_OPTIMIZER
+Solver name: No optimizer attached.
+
+julia> @variable(model, p, Poly(X))
+(_[1]) + (_[2])y + (_[3])x + (_[4])y² + (_[5])xy + (_[6])x²

This creates a vector of decision variables a and sets p as the scalar product between a and X.

Just like with classical JuMP's decision variables, containers of polynomial variables can be created as follows:

julia> @variable(model, [1:3, 1:4], Poly(X))       # Creates a Matrix
+3×4 Matrix{Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}, VariableRef}}:
+ (_[7]) + (_[8])y + (_[9])x + (_[10])y² + (_[11])xy + (_[12])x²     …  (_[61]) + (_[62])y + (_[63])x + (_[64])y² + (_[65])xy + (_[66])x²
+ (_[13]) + (_[14])y + (_[15])x + (_[16])y² + (_[17])xy + (_[18])x²     (_[67]) + (_[68])y + (_[69])x + (_[70])y² + (_[71])xy + (_[72])x²
+ (_[19]) + (_[20])y + (_[21])x + (_[22])y² + (_[23])xy + (_[24])x²     (_[73]) + (_[74])y + (_[75])x + (_[76])y² + (_[77])xy + (_[78])x²
+
+julia> @variable(model, [[:a, :b], -2:2], Poly(X)) # Creates a DenseAxisArray
+2-dimensional DenseAxisArray{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, VariableRef},2,...} with index sets:
+    Dimension 1, [:a, :b]
+    Dimension 2, -2:2
+And data, a 2×5 Matrix{DynamicPolynomials.Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, MultivariatePolynomials.Graded{MultivariatePolynomials.LexOrder}, VariableRef}}:
+ (_[79]) + (_[80])y + (_[81])x + (_[82])y² + (_[83])xy + (_[84])x²  …  (_[127]) + (_[128])y + (_[129])x + (_[130])y² + (_[131])xy + (_[132])x²
+ (_[85]) + (_[86])y + (_[87])x + (_[88])y² + (_[89])xy + (_[90])x²     (_[133]) + (_[134])y + (_[135])x + (_[136])y² + (_[137])xy + (_[138])x²
+
+julia> @variable(model, [i=1:3, j=i:3], Poly(X))   # Creates a SparseAxisArray
+JuMP.Containers.SparseAxisArray{Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}, VariableRef}, 2, Tuple{Int64, Int64}} with 6 entries:
+  [1, 1]  =  (_[139]) + (_[140])*y + (_[141])*x + (_[142])*y^2 + (_[143])*x*y + (_[144])*x^2
+  [1, 2]  =  (_[145]) + (_[146])*y + (_[147])*x + (_[148])*y^2 + (_[149])*x*y + (_[150])*x^2
+  [1, 3]  =  (_[151]) + (_[152])*y + (_[153])*x + (_[154])*y^2 + (_[155])*x*y + (_[156])*x^2
+  [2, 2]  =  (_[157]) + (_[158])*y + (_[159])*x + (_[160])*y^2 + (_[161])*x*y + (_[162])*x^2
+  [2, 3]  =  (_[163]) + (_[164])*y + (_[165])*x + (_[166])*y^2 + (_[167])*x*y + (_[168])*x^2
+  [3, 3]  =  (_[169]) + (_[170])*y + (_[171])*x + (_[172])*y^2 + (_[173])*x*y + (_[174])*x^2

For more flexibility, polynomials parametrized by decision variables can also be created "by hand" for instance as follows:

julia> @variable(model, α)
+α
+
+julia> @variable(model, β)
+β
+
+julia> p = α*x^2 + (α+β)*y^2*x + β*y^3
+(α)x² + (β)y³ + (α + β)xy²

The coefficients of the polynomial can even be quadratic, e.g.

julia> p = (3α^2+β)*x^2 + (α*β+2β)*y^2*x + β*y^3
+(3 α² + β)x² + (β)y³ + (α*β + 2 β)xy²

Let me stress again the distinction between α and β which are decision variables and x and y which are polynomial variables.

Nonnegative polynomial variables

In order to create a sum-of-squares polynomial variable, the syntax is exactly the same except SOSPoly should be used instead of Poly. For instance, the following code creates a $3 \times 4$ matrix of sum-of-squares polynomial variables:

julia> @variable(model, [1:2], SOSPoly(X))
+2-element Vector{GramMatrix{VariableRef, MonomialBasis{Monomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}, MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}}, AffExpr, SymMatrix{VariableRef}}}:
+ GramMatrix with row/column basis:
+ MonomialBasis([1, y, x, y^2, x*y, x^2])
+And entries in a 6×6 SymMatrix{VariableRef}:
+ _[177]  _[178]  _[180]  _[183]  _[187]  _[192]
+ _[178]  _[179]  _[181]  _[184]  _[188]  _[193]
+ _[180]  _[181]  _[182]  _[185]  _[189]  _[194]
+ _[183]  _[184]  _[185]  _[186]  _[190]  _[195]
+ _[187]  _[188]  _[189]  _[190]  _[191]  _[196]
+ _[192]  _[193]  _[194]  _[195]  _[196]  _[197]
+ GramMatrix with row/column basis:
+ MonomialBasis([1, y, x, y^2, x*y, x^2])
+And entries in a 6×6 SymMatrix{VariableRef}:
+ _[198]  _[199]  _[201]  _[204]  _[208]  _[213]
+ _[199]  _[200]  _[202]  _[205]  _[209]  _[214]
+ _[201]  _[202]  _[203]  _[206]  _[210]  _[215]
+ _[204]  _[205]  _[206]  _[207]  _[211]  _[216]
+ _[208]  _[209]  _[210]  _[211]  _[212]  _[217]
+ _[213]  _[214]  _[215]  _[216]  _[217]  _[218]

There is however an important difference between the meaning of the vector of monomials X between Poly and SOSPoly. For SOSPoly, it creates a positive semidefinite matrix of variables Q and sets p as the value of X' * Q * X. That is, for instance, if X contains all the monomials of degree 2, then all the monomials of p will have degree 4 (i.e. p will be a quartic form).

Similarly, to create diagonally-dominant-sum-of-squares polynomial variables (see [Definition 3.1, AM17]), use DSOSPoly(X). This creates a diagonally dominant matrix of variables Q and sets the polynomial variables as the value of X' * Q * X.

Finally, to create scaled-diagonally-dominant-sum-of-squares polynomial variables (see [Definition 3.2, AM17]), use SDSOSPoly(X). This creates a scaled diagonally dominant matrix of variables Q and sets the polynomial variables as the value of X' * Q * X.

Choosing a polynomial basis

In the previous section, we show how to create polynomial variables from a monomial basis. However, the monomial basis is only a particular case of polynomial basis and while using a different basis of the same space of polynomial is would give an equivalent program, it might be more stable numerically (see [Section 3.1.5, BPT12]).

For instance, creating an univariate cubic polynomial variable p using the Chebyshev basis can be done as follows:

julia> cheby_basis = FixedPolynomialBasis([1, x, 2x^2-1, 4x^3-3x])
+FixedPolynomialBasis([1, x, -1 + 2x², -3x + 4x³])
+
+julia> @variable(model, variable_type=Poly(cheby_basis))
+(_[219] - _[221]) + (_[220] - 3 _[222])x + (2 _[221])x² + (4 _[222])x³

and to create a quadratic form variable q using the scaled monomial basis (see [Section 3.1.5, BPT12]), use the following:

julia> X = monomials([x, y], 2)
+3-element MonomialVector{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}}:
+ y²
+ xy
+ x²
+
+julia> scaled_basis = ScaledMonomialBasis(X)
+ScaledMonomialBasis([y², xy, x²])
+
+julia> @variable(model, variable_type=Poly(scaled_basis))
+(_[223])y² + (1.4142135623730951 _[224])xy + (_[225])x²

which is equivalent to

julia> scaled_basis = FixedPolynomialBasis([x^2, √2*x*y, y^2])
+FixedPolynomialBasis([x², 1.4142135623730951xy, y²])
+
+julia> @variable(model, variable_type=Poly(scaled_basis))
+(_[228])y² + (1.4142135623730951 _[227])xy + (_[226])x²

References

[BPT12] Blekherman, G.; Parrilo, P. A. & Thomas, R. R. Semidefinite Optimization and Convex Algebraic Geometry. Society for Industrial and Applied Mathematics, 2012.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.

Reference

PolyJuMP.PolyType
struct Poly{PB<:AbstractPolynomialBasis} <: AbstractPoly
+    polynomial_basis::PB
+end

Polynomial variable $v^\top p$ where $v$ is a vector of new decision variables and $p$ is a vector of polynomials for the basis polynomial_basis.

source

Variable bridges:

SumOfSquares.Bridges.Variable.ScaledDiagonallyDominantBridgeType
struct ScaledDiagonallyDominantBridge{T} <: MOI.Bridges.Variable.AbstractBridge
+    side_dimension::Int
+    variables::Vector{Vector{MOI.VariableIndex}}
+    constraints::Vector{MOI.ConstraintIndex{
+        MOI.VectorOfVariables, SOS.PositiveSemidefinite2x2ConeTriangle}}
+end

A matrix is SDD iff it is the sum of psd matrices Mij that are zero except for entries ii, ij and jj [Lemma 9, AM17]. This bridge substitute the constrained variables in SOS.ScaledDiagonallyDominantConeTriangle into a sum of constrained variables in SOS.PositiveSemidefinite2x2ConeTriangle.

[AM17] Ahmadi, A. A. & Majumdar, A. DSOS and SDSOS Optimization: More Tractable Alternatives to Sum of Squares and Semidefinite Optimization ArXiv e-prints, 2017.

source