@ -0,0 +1,36 @@
|
||||
@media screen and (min-width: 1056px) {
|
||||
#documenter .docs-main {
|
||||
max-width: 65rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tbody, thead, pre {
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
table td, th {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table td code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
table tr,
|
||||
table th {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
table tr:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: transparent;
|
||||
color: rgb(232, 62, 140);
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
// Generated by Documenter.jl
|
||||
requirejs.config({
|
||||
paths: {
|
||||
'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/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.12.1/jquery-ui.min',
|
||||
'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/contrib/auto-render.min',
|
||||
'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.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.13.24/katex.min',
|
||||
'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min',
|
||||
'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/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([], function() {
|
||||
function addCopyButtonCallbacks() {
|
||||
for (const el of document.getElementsByTagName("pre")) {
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("copy-button", "fas", "fa-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-times");
|
||||
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-times");
|
||||
}, 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($) {
|
||||
|
||||
// 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($) {
|
||||
|
||||
// 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($) {
|
||||
|
||||
function set_theme(theme) {
|
||||
var active = null;
|
||||
var disabled = [];
|
||||
for (var i = 0; i < document.styleSheets.length; i++) {
|
||||
var ss = document.styleSheets[i];
|
||||
var themename = ss.ownerNode.getAttribute("data-theme-name");
|
||||
if(themename === null) continue; // ignore non-theme stylesheets
|
||||
// Find the active theme
|
||||
if(themename === theme) active = ss;
|
||||
else disabled.push(ss);
|
||||
}
|
||||
if(active !== null) {
|
||||
active.disabled = false;
|
||||
if(active.ownerNode.getAttribute("data-theme-primary") === null) {
|
||||
document.getElementsByTagName('html')[0].className = "theme--" + theme;
|
||||
} else {
|
||||
document.getElementsByTagName('html')[0].className = "";
|
||||
}
|
||||
disabled.forEach(function(ss){
|
||||
ss.disabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Store the theme in localStorage
|
||||
if(typeof(window.localStorage) !== "undefined") {
|
||||
window.localStorage.setItem("documenter-theme", theme);
|
||||
} else {
|
||||
console.error("Browser does not support window.localStorage");
|
||||
}
|
||||
}
|
||||
|
||||
// Theme picker setup
|
||||
$(document).ready(function() {
|
||||
// onchange callback
|
||||
$('#documenter-themepicker').change(function themepick_callback(ev){
|
||||
var themename = $('#documenter-themepicker option:selected').attr('value');
|
||||
set_theme(themename);
|
||||
});
|
||||
|
||||
// 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);
|
||||
})
|
||||
} else {
|
||||
$('#documenter-themepicker option').each(function(i,e) {
|
||||
e.selected = $("html").hasClass(`theme--${e.value}`);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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 = $("<option value='#' selected='selected'>" + DOCUMENTER_CURRENT_VERSION + "</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 = $("<option value='" + version_url + "'>" + each + "</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");
|
||||
}
|
||||
})
|
||||
|
||||
})
|
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 586 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,267 @@
|
||||
// Generated by Documenter.jl
|
||||
requirejs.config({
|
||||
paths: {
|
||||
'lunr': 'https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.9/lunr.min',
|
||||
'lodash': 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min',
|
||||
'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min',
|
||||
}
|
||||
});
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
require(['jquery', 'lunr', 'lodash'], function($, lunr, _) {
|
||||
|
||||
$(document).ready(function() {
|
||||
// parseUri 1.2.2
|
||||
// (c) Steven Levithan <stevenlevithan.com>
|
||||
// MIT License
|
||||
function parseUri (str) {
|
||||
var o = parseUri.options,
|
||||
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
|
||||
uri = {},
|
||||
i = 14;
|
||||
|
||||
while (i--) uri[o.key[i]] = m[i] || "";
|
||||
|
||||
uri[o.q.name] = {};
|
||||
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
|
||||
if ($1) uri[o.q.name][$1] = $2;
|
||||
});
|
||||
|
||||
return uri;
|
||||
};
|
||||
parseUri.options = {
|
||||
strictMode: false,
|
||||
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
|
||||
q: {
|
||||
name: "queryKey",
|
||||
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
|
||||
},
|
||||
parser: {
|
||||
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
|
||||
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
|
||||
}
|
||||
};
|
||||
|
||||
$("#search-form").submit(function(e) {
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
// 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
|
||||
lunr.stopWordFilter = lunr.generateStopWordFilter([
|
||||
'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'
|
||||
])
|
||||
|
||||
// add . as a separator, because otherwise "title": "Documenter.Anchors.add!"
|
||||
// would not find anything if searching for "add!", only for the entire qualification
|
||||
lunr.tokenizer.separator = /[\s\-\.]+/
|
||||
|
||||
// custom trimmer that doesn't strip @ and !, which are used in julia macro and function names
|
||||
lunr.trimmer = function (token) {
|
||||
return token.update(function (s) {
|
||||
return s.replace(/^[^a-zA-Z0-9@!]+/, '').replace(/[^a-zA-Z0-9@!]+$/, '')
|
||||
})
|
||||
}
|
||||
|
||||
lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'juliaStopWordFilter')
|
||||
lunr.Pipeline.registerFunction(lunr.trimmer, 'juliaTrimmer')
|
||||
|
||||
var index = lunr(function () {
|
||||
this.ref('location')
|
||||
this.field('title',{boost: 100})
|
||||
this.field('text')
|
||||
documenterSearchIndex['docs'].forEach(function(e) {
|
||||
this.add(e)
|
||||
}, this)
|
||||
})
|
||||
var store = {}
|
||||
|
||||
documenterSearchIndex['docs'].forEach(function(e) {
|
||||
store[e.location] = {title: e.title, category: e.category, page: e.page}
|
||||
})
|
||||
|
||||
$(function(){
|
||||
searchresults = $('#documenter-search-results');
|
||||
searchinfo = $('#documenter-search-info');
|
||||
searchbox = $('#documenter-search-query');
|
||||
searchform = $('.docs-search');
|
||||
sidebar = $('.docs-sidebar');
|
||||
function update_search(querystring) {
|
||||
tokens = lunr.tokenizer(querystring)
|
||||
results = index.query(function (q) {
|
||||
tokens.forEach(function (t) {
|
||||
q.term(t.toString(), {
|
||||
fields: ["title"],
|
||||
boost: 100,
|
||||
usePipeline: true,
|
||||
editDistance: 0,
|
||||
wildcard: lunr.Query.wildcard.NONE
|
||||
})
|
||||
q.term(t.toString(), {
|
||||
fields: ["title"],
|
||||
boost: 10,
|
||||
usePipeline: true,
|
||||
editDistance: 2,
|
||||
wildcard: lunr.Query.wildcard.NONE
|
||||
})
|
||||
q.term(t.toString(), {
|
||||
fields: ["text"],
|
||||
boost: 1,
|
||||
usePipeline: true,
|
||||
editDistance: 0,
|
||||
wildcard: lunr.Query.wildcard.NONE
|
||||
})
|
||||
})
|
||||
})
|
||||
searchinfo.text("Number of results: " + results.length)
|
||||
searchresults.empty()
|
||||
results.forEach(function(result) {
|
||||
data = store[result.ref]
|
||||
link = $('<a class="docs-label">'+data.title+'</a>')
|
||||
link.attr('href', documenterBaseURL+'/'+result.ref)
|
||||
if (data.category != "page"){
|
||||
cat = $('<span class="docs-category">('+data.category+', '+data.page+')</span>')
|
||||
} else {
|
||||
cat = $('<span class="docs-category">('+data.category+')</span>')
|
||||
}
|
||||
li = $('<li>').append(link).append(" ").append(cat)
|
||||
searchresults.append(li)
|
||||
})
|
||||
}
|
||||
|
||||
function update_search_box() {
|
||||
querystring = searchbox.val()
|
||||
update_search(querystring)
|
||||
}
|
||||
|
||||
searchbox.keyup(_.debounce(update_search_box, 250))
|
||||
searchbox.change(update_search_box)
|
||||
|
||||
// Disable enter-key form submission for the searchbox on the search page
|
||||
// and just re-run search rather than refresh the whole page.
|
||||
searchform.keypress(
|
||||
function(event){
|
||||
if (event.which == '13') {
|
||||
if (sidebar.hasClass('visible')) {
|
||||
sidebar.removeClass('visible');
|
||||
}
|
||||
update_search_box();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
search_query_uri = parseUri(window.location).queryKey["q"]
|
||||
if(search_query_uri !== undefined) {
|
||||
search_query = decodeURIComponent(search_query_uri.replace(/\+/g, '%20'))
|
||||
searchbox.val(search_query)
|
||||
}
|
||||
update_search_box();
|
||||
})
|
||||
})
|
||||
|
||||
})
|
@ -0,0 +1,66 @@
|
||||
// Small function to quickly swap out themes. Gets put into the <head> tag..
|
||||
function set_theme_from_local_storage() {
|
||||
// Intialize 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 browser supports user color preference
|
||||
var darkPreference = false;
|
||||
// Check if the users preference is for dark color scheme
|
||||
if(window.matchMedia('(prefers-color-scheme: dark)').matches === true) {
|
||||
darkPreference = 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 darkTheme = null;
|
||||
for (var i = 0; i < document.styleSheets.length; i++) {
|
||||
var ss = document.styleSheets[i];
|
||||
// The <link> 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.
|
||||
var isprimary = (ss.ownerNode.getAttribute("data-theme-primary") !== null);
|
||||
// Check if the theme is primary dark theme
|
||||
var isDarkTheme = (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null);
|
||||
// If ss is for dark theme then set the value of darkTheme to the name of the theme
|
||||
if(isDarkTheme) darkTheme = 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);
|
||||
}
|
||||
if(active !== null) {
|
||||
// If we did find an active theme, we'll (1) add the theme--$(theme) class to <html>
|
||||
document.getElementsByTagName('html')[0].className = "theme--" + theme;
|
||||
// and (2) disable all the other theme stylesheets
|
||||
disabled.forEach(function(ss){
|
||||
ss.disabled = true;
|
||||
});
|
||||
}
|
||||
else if(darkTheme !== null && darkPreference === true) {
|
||||
// If we did find an active theme, we'll (1) add the theme--$(theme) class to <html>
|
||||
document.getElementsByTagName('html')[0].className = "theme--" + darkTheme;
|
||||
// and (2) disable all the other theme stylesheets
|
||||
disabled.forEach(function(ss){
|
||||
if (ss.ownerNode.getAttribute("data-theme-name") !== darkTheme) {
|
||||
ss.disabled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
set_theme_from_local_storage();
|
@ -0,0 +1,49 @@
|
||||
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.<br><a href="' + href + '">Click here to go to the documentation for the latest stable release.</a>';
|
||||
div.appendChild(closer);
|
||||
document.body.appendChild(div);
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', maybeAddWarning);
|
||||
} else {
|
||||
maybeAddWarning();
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Home · RELOG</title><script data-outdated-warner src="assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="assets/documenter.js"></script><script src="siteinfo.js"></script><script src="../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="assets/themeswap.js"></script><link href="assets/custom.css" rel="stylesheet" type="text/css"/></head><body><div id="documenter"><nav class="docs-sidebar"><div class="docs-package-name"><span class="docs-autofit"><a href>RELOG</a></span></div><form class="docs-search" action="search/"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li class="is-active"><a class="tocitem" href>Home</a></li><li><a class="tocitem" href="usage/">Usage</a></li><li><a class="tocitem" href="format/">Input and Output Data Formats</a></li><li><a class="tocitem" href="reports/">Simplified Solution Reports</a></li><li><a class="tocitem" href="model/">Optimization Model</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li class="is-active"><a href>Home</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Home</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://github.com/ANL-CEEESA/RELOG/blob/master/docs/src/index.md" title="Edit on GitHub"><span class="docs-icon fab"></span><span class="docs-label is-hidden-touch">Edit on GitHub</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="RELOG:-Reverse-Logistics-Optimization"><a class="docs-heading-anchor" href="#RELOG:-Reverse-Logistics-Optimization">RELOG: Reverse Logistics Optimization</a><a id="RELOG:-Reverse-Logistics-Optimization-1"></a><a class="docs-heading-anchor-permalink" href="#RELOG:-Reverse-Logistics-Optimization" title="Permalink"></a></h1><p><strong>RELOG</strong> is an open-source supply chain optimization package focusing on reverse logistics and reverse manufacturing. The package uses Mixed-Integer Linear Programming to determine where to build recycling plants, what size should these plants have and which customers should be served by which plants. The package supports custom reverse logistics pipelines, with multiple types of plants, multiple types of product and multiple time periods.</p><center>
|
||||
<img src="assets/ex_transportation.png" width="1000px"/>
|
||||
</center><h3 id="Table-of-Contents"><a class="docs-heading-anchor" href="#Table-of-Contents">Table of Contents</a><a id="Table-of-Contents-1"></a><a class="docs-heading-anchor-permalink" href="#Table-of-Contents" title="Permalink"></a></h3><ul><li><a href="usage/#Usage">Usage</a></li><li class="no-marker"><ul><li><a href="usage/#.-Installation">1. Installation</a></li><li><a href="usage/#.-Modeling-the-problem">2. Modeling the problem</a></li><li><a href="usage/#.-Running-the-optimization">3. Running the optimization</a></li><li><a href="usage/#.-What-If-Analysis">4. What-If Analysis</a></li><li><a href="usage/#.-Advanced-options">5. Advanced options</a></li><li class="no-marker"><ul><li><a href="usage/#.1-Changing-the-solver">5.1 Changing the solver</a></li><li><a href="usage/#.2-Multi-period-heuristics">5.2 Multi-period heuristics</a></li></ul></li></ul></li><li><a href="format/#Input-and-Output-Data-Formats">Input and Output Data Formats</a></li><li class="no-marker"><ul><li><a href="format/#Input-Data-Format-(JSON)">Input Data Format (JSON)</a></li><li class="no-marker"><ul><li><a href="format/#Parameters">Parameters</a></li><li><a href="format/#Products">Products</a></li><li><a href="format/#Processing-plants">Processing plants</a></li><li><a href="format/#Geographic-database">Geographic database</a></li><li><a href="format/#Current-limitations">Current limitations</a></li></ul></li><li><a href="format/#Output-Data-Format-(JSON)">Output Data Format (JSON)</a></li></ul></li><li><a href="reports/#Simplified-Solution-Reports">Simplified Solution Reports</a></li><li class="no-marker"><ul><li><a href="reports/#Plants-report">Plants report</a></li><li class="no-marker"><ul><li><a href="reports/#Sample-charts">Sample charts</a></li></ul></li><li><a href="reports/#Plant-outputs-report">Plant outputs report</a></li><li class="no-marker"><ul><li><a href="reports/#Sample-charts-2">Sample charts</a></li></ul></li><li><a href="reports/#Plant-emissions-report">Plant emissions report</a></li><li class="no-marker"><ul><li><a href="reports/#Sample-charts-3">Sample charts</a></li></ul></li><li><a href="reports/#Products-report">Products report</a></li><li><a href="reports/#Transportation-report">Transportation report</a></li><li class="no-marker"><ul><li><a href="reports/#Sample-charts-4">Sample charts</a></li></ul></li><li><a href="reports/#Transportation-emissions-report">Transportation emissions report</a></li><li class="no-marker"><ul><li><a href="reports/#Sample-charts-5">Sample charts</a></li></ul></li></ul></li><li><a href="model/#Optimization-Model">Optimization Model</a></li><li class="no-marker"><ul><li><a href="model/#Mathematical-Description">Mathematical Description</a></li><li class="no-marker"><ul><li><a href="model/#Sets">Sets</a></li><li><a href="model/#Constants">Constants</a></li><li><a href="model/#Decision-variables">Decision variables</a></li><li><a href="model/#Objective-function">Objective function</a></li><li><a href="model/#Constraints">Constraints</a></li></ul></li></ul></li></ul><h3 id="Source-Code"><a class="docs-heading-anchor" href="#Source-Code">Source Code</a><a id="Source-Code-1"></a><a class="docs-heading-anchor-permalink" href="#Source-Code" title="Permalink"></a></h3><ul><li><a href="https://github.com/ANL-CEEESA/RELOG">https://github.com/ANL-CEEESA/RELOG</a></li></ul><h3 id="Authors"><a class="docs-heading-anchor" href="#Authors">Authors</a><a id="Authors-1"></a><a class="docs-heading-anchor-permalink" href="#Authors" title="Permalink"></a></h3><ul><li><strong>Alinson S. Xavier,</strong> Argonne National Laboratory <axavier@anl.gov></li><li><strong>Nwike Iloeje,</strong> Argonne National Laboratory <ciloeje@anl.gov></li></ul><h3 id="License"><a class="docs-heading-anchor" href="#License">License</a><a id="License-1"></a><a class="docs-heading-anchor-permalink" href="#License" title="Permalink"></a></h3><pre><code class="language-text hljs">RELOG: Reverse Logistics Optimization
|
||||
Copyright © 2020, UChicago Argonne, LLC. All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.</code></pre></article><nav class="docs-footer"><a class="docs-footer-nextpage" href="usage/">Usage »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.24 on <span class="colophon-date" title="Thursday 23 February 2023 11:10">Thursday 23 February 2023</span>. Using Julia version 1.8.2.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
@ -0,0 +1,2 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Search · RELOG</title><script data-outdated-warner src="../assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../assets/themeswap.js"></script><link href="../assets/custom.css" rel="stylesheet" type="text/css"/></head><body><div id="documenter"><nav class="docs-sidebar"><div class="docs-package-name"><span class="docs-autofit"><a href="../">RELOG</a></span></div><form class="docs-search" action><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="../">Home</a></li><li><a class="tocitem" href="../usage/">Usage</a></li><li><a class="tocitem" href="../format/">Input and Output Data Formats</a></li><li><a class="tocitem" href="../reports/">Simplified Solution Reports</a></li><li><a class="tocitem" href="../model/">Optimization Model</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li class="is-active"><a href>Search</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Search</a></li></ul></nav><div class="docs-right"><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article><p id="documenter-search-info">Loading search...</p><ul id="documenter-search-results"></ul></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.24 on <span class="colophon-date" title="Thursday 23 February 2023 11:10">Thursday 23 February 2023</span>. Using Julia version 1.8.2.</p></section><footer class="modal-card-foot"></footer></div></div></div></body><script src="../search_index.js"></script><script src="../assets/search.js"></script></html>
|
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Usage · RELOG</title><script data-outdated-warner src="../assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../assets/themeswap.js"></script><link href="../assets/custom.css" rel="stylesheet" type="text/css"/></head><body><div id="documenter"><nav class="docs-sidebar"><div class="docs-package-name"><span class="docs-autofit"><a href="../">RELOG</a></span></div><form class="docs-search" action="../search/"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="../">Home</a></li><li class="is-active"><a class="tocitem" href>Usage</a><ul class="internal"><li><a class="tocitem" href="#.-Installation"><span>1. Installation</span></a></li><li><a class="tocitem" href="#.-Modeling-the-problem"><span>2. Modeling the problem</span></a></li><li><a class="tocitem" href="#.-Running-the-optimization"><span>3. Running the optimization</span></a></li><li><a class="tocitem" href="#.-What-If-Analysis"><span>4. What-If Analysis</span></a></li><li><a class="tocitem" href="#.-Advanced-options"><span>5. Advanced options</span></a></li></ul></li><li><a class="tocitem" href="../format/">Input and Output Data Formats</a></li><li><a class="tocitem" href="../reports/">Simplified Solution Reports</a></li><li><a class="tocitem" href="../model/">Optimization Model</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li class="is-active"><a href>Usage</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Usage</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://github.com/ANL-CEEESA/RELOG/blob/master/docs/src/usage.md" title="Edit on GitHub"><span class="docs-icon fab"></span><span class="docs-label is-hidden-touch">Edit on GitHub</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Usage"><a class="docs-heading-anchor" href="#Usage">Usage</a><a id="Usage-1"></a><a class="docs-heading-anchor-permalink" href="#Usage" title="Permalink"></a></h1><h2 id=".-Installation"><a class="docs-heading-anchor" href="#.-Installation">1. Installation</a><a id=".-Installation-1"></a><a class="docs-heading-anchor-permalink" href="#.-Installation" title="Permalink"></a></h2><p>To use RELOG, the first step is to install the <a href="https://julialang.org/">Julia programming language</a> on your machine. Note that RELOG was developed and tested with Julia 1.8 and may not be compatible with newer versions. After Julia is installed, launch the Julia console, then run:</p><pre><code class="language-julia hljs">using Pkg
|
||||
Pkg.add(name="RELOG", version="0.6")</code></pre><h2 id=".-Modeling-the-problem"><a class="docs-heading-anchor" href="#.-Modeling-the-problem">2. Modeling the problem</a><a id=".-Modeling-the-problem-1"></a><a class="docs-heading-anchor-permalink" href="#.-Modeling-the-problem" title="Permalink"></a></h2><p>The two main model components in RELOG are <strong>products</strong> and <strong>plants</strong>.</p><p>A <strong>product</strong> is any material that needs to be recycled, any intermediary product produced during the recycling process, or any product recovered at the end of the process. For example, in a NiMH battery recycling study case, products could include (i) the original batteries to be recycled; (ii) the cathode and anode parts of the battery; (iii) rare-earth elements and (iv) scrap metals.</p><ul><li><p>The model assumes that some products are initially available at user-specified locations (described by their latitude, longitude and the amount available), while other products only become available during the recycling process.</p></li><li><p>Products that are initially available must be sent to a plant for processing during the same time period they became available.</p></li><li><p>Transporting products from one location to another incurs a transportation cost (<code>$/km/tonne</code>), spends some amount of energy (<code>J/km/tonne</code>) and may generate multiple types of emissions (<code>tonne/tonne</code>). All these parameters are user-specified and may be product- and time-specific.</p></li></ul><p>A <strong>plant</strong> is a facility that converts one type of product to another. RELOG assumes that each plant receives a single type of product as input and converts this input into multiple types of products. Multiple types of plants, with different inputs, outputs and performance characteristics, may be specified. In the NiMH battery recycling study case, for example, one type of plant could be a <em>disassembly plant</em>, which converts <em>batteries</em> into <em>cathode</em> and <em>anode</em>. Another type of plant could be <em>anode recycling plant</em>, which converts <em>anode</em> into <em>rare-earth elements</em> and <em>scrap metals</em>.</p><ul><li><p>To process each tonne of input material, plants incur a variable operating cost (<code>$/tonne</code>), spend some amount of energy (<code>GJ/tonne</code>), and produce multiple types of emissions (<code>tonne/tonne</code>). Plants also incur a fixed operating cost (<code>$</code>) regardless of the amount of material they process. All these parameters are user-specified and may be region- and time-specific.</p></li><li><p>Plants can be built at user-specified potential locations. Opening a plant incurs a one-time opening cost (<code>$</code>) which may be region- and time-specific. Plants also have a limited capacity (in <code>tonne</code>), which indicates the maximum amount of input material they are able to process per year. When specifying potential locations for each type of plant, it is also possible to specify the minimum and maximum capacity of the plants that can be built at that particular location. Different plants sizes may have different opening costs and fixed operating costs. After a plant is built, it can be further expanded in the following years, up to its maximum capacity.</p></li><li><p>Products received by a plant can be either processed immediately or stored for later processing. Plants have a maximum storage capacity (<code>tonne</code>). Storage costs (<code>$/tonne</code>) can also be specified.</p></li><li><p>All products generated by a plant can either be sent to another plant for further processing, or disposed of locally for either a profit or a loss (<code>$/tonne</code>). To model environmental regulations, it is also possible to specify the maximum amount of each product that can be disposed of at each location.</p></li></ul><p>All user parameters specified above must be provided to RELOG as a JSON file, which is fully described in the <a href="../format/">data format page</a>.</p><h2 id=".-Running-the-optimization"><a class="docs-heading-anchor" href="#.-Running-the-optimization">3. Running the optimization</a><a id=".-Running-the-optimization-1"></a><a class="docs-heading-anchor-permalink" href="#.-Running-the-optimization" title="Permalink"></a></h2><p>After creating a JSON file describing the reverse manufacturing process and the input data, the following example illustrates how to use the package to find the optimal set of decisions:</p><pre><code class="language-julia hljs"># Import package
|
||||
using RELOG
|
||||
|
||||
# Solve optimization problem
|
||||
solution = RELOG.solve("/home/user/instance.json")
|
||||
|
||||
# Write full solution in JSON format
|
||||
RELOG.write(solution, "solution.json")
|
||||
|
||||
# Write simplified reports in CSV format
|
||||
RELOG.write_plants_report(solution, "plants.csv")
|
||||
RELOG.write_transportation_report(solution, "transportation.csv")</code></pre><p>For a complete description of the file formats above, and for a complete list of available reports, see the <a href="../format/">data format page</a>.</p><h2 id=".-What-If-Analysis"><a class="docs-heading-anchor" href="#.-What-If-Analysis">4. What-If Analysis</a><a id=".-What-If-Analysis-1"></a><a class="docs-heading-anchor-permalink" href="#.-What-If-Analysis" title="Permalink"></a></h2><p>Fundamentally, RELOG decides when and where to build plants based on a deterministic optimization problem that minimizes costs for a particular input file provided by the user. In practical situations, it may not be possible to perfectly estimate some (or most) entries in this input file in advance, such as costs, demands and emissions. In this situation, it may be interesting to evaluate how well does the facility location plan produced by RELOG work if costs, demands and emissions turn out to be different.</p><p>To simplify this what-if analysis, RELOG provides the <code>resolve</code> method, which updates a previous solution based on a new scenario, but keeps some of the previous decisions fixed. More precisely, given an optimal solution produced by RELOG and a new input file describing the new scenario, the <code>resolve</code> method reoptimizes the supply chain and produces a new solution which still builds the same set of plants as before, in exactly the same locations and with the same capacities, but that may now utilize the plants differently, based on the new data. For example, in the new solution, plants that were previously used at full capacity may now be utilized at half-capacity instead. As another example, regions that were previously served by a certain plant may now be served by a different one.</p><p>The following snippet shows how to use the method:</p><pre><code class="language-julia hljs"># Import package
|
||||
using RELOG
|
||||
|
||||
# Optimize for the average scenario
|
||||
solution_avg, model_avg = RELOG.solve("input_avg.json", return_model=true)
|
||||
|
||||
# Write reports for the average scenario
|
||||
RELOG.write_plants_report(solution_avg, "plants_avg.csv")
|
||||
RELOG.write_transportation_report(solution_avg, "transportation_avg.csv")
|
||||
|
||||
# Re-optimize for the high-demand scenario, keeping plants fixed
|
||||
solution_high = RELOG.resolve(model_avg, "input_high.json")
|
||||
|
||||
# Write reports for the high-demand scenario
|
||||
RELOG.write_plants_report(solution_high, "plants_high.csv")
|
||||
RELOG.write_transportation_report(solution_high, "transportation_high.csv")</code></pre><p>To use the <code>resolve</code> method, the new input file should be very similar to the original one. Only the following entries are allowed to change:</p><ul><li><strong>Products:</strong> Transportation costs, energy, emissions and initial amounts (latitude, longitude and amount).</li><li><strong>Plants:</strong> Energy and emissions.</li><li><strong>Plant's location:</strong> Latitude and longitude.</li><li><strong>Plant's storage:</strong> Cost.</li><li><strong>Plant's capacity:</strong> Opening cost, fixed operating cost and variable operating cost.</li></ul><h2 id=".-Advanced-options"><a class="docs-heading-anchor" href="#.-Advanced-options">5. Advanced options</a><a id=".-Advanced-options-1"></a><a class="docs-heading-anchor-permalink" href="#.-Advanced-options" title="Permalink"></a></h2><h3 id=".1-Changing-the-solver"><a class="docs-heading-anchor" href="#.1-Changing-the-solver">5.1 Changing the solver</a><a id=".1-Changing-the-solver-1"></a><a class="docs-heading-anchor-permalink" href="#.1-Changing-the-solver" title="Permalink"></a></h3><p>By default, RELOG internally uses <a href="https://github.com/ERGO-Code/HiGHS">HiGHS</a>, an open-source and freely-available Mixed-Integer Linear Programming solver. For larger-scale test cases, a commercial solver such as Gurobi, CPLEX or XPRESS is recommended. The following snippet shows how to switch to Gurobi, for example:</p><pre><code class="language-julia hljs">using RELOG, Gurobi, JuMP
|
||||
|
||||
gurobi = optimizer_with_attributes(
|
||||
Gurobi.Optimizer,
|
||||
"TimeLimit" => 3600,
|
||||
"MIPGap" => 0.001,
|
||||
)
|
||||
|
||||
RELOG.solve(
|
||||
"instance.json",
|
||||
output="solution.json",
|
||||
optimizer=gurobi,
|
||||
)</code></pre><h3 id=".2-Multi-period-heuristics"><a class="docs-heading-anchor" href="#.2-Multi-period-heuristics">5.2 Multi-period heuristics</a><a id=".2-Multi-period-heuristics-1"></a><a class="docs-heading-anchor-permalink" href="#.2-Multi-period-heuristics" title="Permalink"></a></h3><p>For large-scale instances, it may be too time-consuming to find an exact optimal solution to the multi-period version of the problem. For these situations, RELOG includes a heuristic solution method, which proceeds as follows:</p><ol><li><p>First, RELOG creates a single-period version of the problem, in which most values are replaced by their averages. This single-period problem is typically much easier to solve.</p></li><li><p>After solving the simplified problem, RELOG resolves the multi-period version of the problem, but considering only candidate plant locations that were selected by the optimal solution to the single-period version of the problem. All remaining candidate plant locations are removed.</p></li></ol><p>To solve an instance using this heuristic, use the option <code>heuristic=true</code>, as shown below.</p><pre><code class="language-julia hljs">using RELOG
|
||||
|
||||
solution = RELOG.solve(
|
||||
"/home/user/instance.json",
|
||||
heuristic=true,
|
||||
)</code></pre></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../">« Home</a><a class="docs-footer-nextpage" href="../format/">Input and Output Data Formats »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.24 on <span class="colophon-date" title="Thursday 23 February 2023 11:10">Thursday 23 February 2023</span>. Using Julia version 1.8.2.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|