(function () { "use strict"; if (typeof window.bigRat !== "function") { throw new Error("bh_bigrat.js muss vor bh_de_minplex.js geladen werden."); } var STYLE_ID = "bh-ratplex-style"; var WRAP_ID = "bh-ratplex-wrap"; var scriptEl = document.currentScript || (function () { var xs = document.getElementsByTagName("script"); return xs[xs.length - 1]; })(); var mountNode = null; function ensureStyle() { if (document.getElementById(STYLE_ID)) return; var style = document.createElement("style"); style.id = STYLE_ID; style.textContent = `/* Ratplex-spezifische Ergänzungen */ #bh-ratplex-wrap { margin: 0 auto !important; padding: 0 !important; background: #D6D2CE !important; display: flex; flex-direction: column; align-items: center; width: 100%; } #bh-ratplex-wrap form, #bh-ratplex-wrap table, #bh-ratplex-wrap tr, #bh-ratplex-wrap td, #bh-ratplex-wrap .row, #bh-ratplex-wrap .form-row, #bh-ratplex-wrap .controls, #bh-ratplex-wrap .slider-block, #bh-ratplex-wrap .dropdown-block, #bh-ratplex-wrap .button-block { background: #D6D2CE !important; } #bh-ratplex-wrap h1 { margin: 0 0 8px 0; font-size: 1.2em; } #bh-ratplex-wrap .note { display: block; margin: 0 0 12px 0; font-size: 14px; } #bh-ratplex-wrap #runtime { display: block; margin-top: 8px; font-size: 14px; width: 100%; max-width: 1080px; text-align: left; }} #bh-ratplex-wrap form[name="ratplex"] { width: 100%; max-width: 1080px; margin: 0 auto !important; } #bh-ratplex-wrap textarea { width: 100%; box-sizing: border-box; font-family: "Courier New", Courier, monospace; font-size: 14px; } #bh-ratplex-wrap textarea[name="data"] { min-height: 245px; } #bh-ratplex-wrap textarea[name="result"] { min-height: 425px; } #bh-ratplex-wrap .row { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; margin-bottom: 10px; } #bh-ratplex-wrap .arrow-row { justify-content: center; } #bh-ratplex-wrap .controls label { white-space: nowrap; } #bh-ratplex-wrap button, #bh-ratplex-wrap input[type="button"], #bh-ratplex-wrap select { font: inherit; }`; document.head.appendChild(style); } function getMountNode() { if (mountNode) return mountNode; var wrap = document.getElementById(WRAP_ID); if (wrap) { mountNode = wrap; return wrap; } wrap = document.createElement("div"); wrap.id = WRAP_ID; var anchor = scriptEl; var p = anchor && anchor.closest ? anchor.closest("p") : null; if (p && p.parentNode) { p.parentNode.insertBefore(wrap, p); } else if (anchor && anchor.parentNode) { anchor.parentNode.insertBefore(wrap, anchor); } else { document.body.appendChild(wrap); } mountNode = wrap; return wrap; } function formMarkup() { return `
`; } function bindUI() { document.ratplex = document.forms.ratplex; var debouncedRandomCompute = debounce(function () { random(true); }, 180); document.getElementById("slider-m").addEventListener("input", function () { updateThumb(this, "thumb-m"); }); document.getElementById("slider-n").addEventListener("input", function () { updateThumb(this, "thumb-n"); }); document.getElementById("slider-m").addEventListener("change", debouncedRandomCompute); document.getElementById("slider-n").addEventListener("change", debouncedRandomCompute); document.getElementById("btn-random").addEventListener("click", function () { random(true); }); document.getElementById("btn-compute").addEventListener("click", compute); document.getElementById("btn-arrow").addEventListener("click", compute); document.getElementById("btn-clear").addEventListener("click", function () { document.ratplex.data.value = ""; document.ratplex.result.value = ""; sourceState.text = ""; sourceState.matrix = null; document.ratplex.x.selectedIndex = 0; document.getElementById("runtime").textContent = ""; }); document.getElementById("x").addEventListener("change", function () { var idx = this.selectedIndex; if (idx > 0) { setSourceText(EXAMPLES[idx]); compute(); } }); var recomputeOnChange = document.querySelectorAll('#' + WRAP_ID + ' input[type="checkbox"], #' + WRAP_ID + ' input[type="radio"]'); recomputeOnChange.forEach(function (el) { el.addEventListener("change", function () { if (document.ratplex.data.value.trim() !== "") compute(); }); }); updateThumb(document.getElementById("slider-m"), "thumb-m"); updateThumb(document.getElementById("slider-n"), "thumb-n"); document.ratplex.x.selectedIndex = 0; document.ratplex.data.value = EXAMPLES[1]; sourceState.text = ""; sourceState.matrix = null; compute(); } function initMinplex() { ensureStyle(); var node = getMountNode(); node.innerHTML = formMarkup(); bindUI(); } var EPSILON = bigRat(1, 10000000000), FACTOR = 25, INFINITY, TAB = 7, ZERO = bigRat(0), a = [], b = [], e = [], n1 = [], n2 = [], s = [], bv = [], mbv = [], nbv = [], tab = [], i, j, k, l, m, n, beq, bet, ble, cb, cn, ms, ns, prog = 1, rule = 1, op = 1, opt = 1, max, min, few = true, less, nor1 = false, nor2 = false, output = false, perts, red = false, scal = false, solve, steps, status, str, tmp, nul = 0, phase1 = false; function nines() { var big = "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"; big += big; return bigRat(big + big); } INFINITY = nines(); var sourceState = { text: "", matrix: null }; var EXAMPLES = { 1: "15 17 -12 -2 15 -6 -4 21\n16 15 -13 -4 -1 -7 -8 0\n-8 -12 -3 -5 16 -6 22 -4\n17 -3 -12 -1 -1 21 14 0\n-7 -9 14 -11 23 -12 21 21\n21 -11 19 -2 -9 -2 16 14\n 0 -2 -3 22 16 16 -3 -11\n14 -10 17 -6 23 23 -12 24\n 0 23 23 24 -6 18 -5 -12", 2: "30 1 3 2\n25 4 2 1\n45 3 4 4\n50 2 3 5\n 0 5 8 4", 3: " 1 1 -8 -2 0 0\n 28 2 8 -2 0 0\n 42 1 -6 1 0 0\n 1 0 1 0 0 0\n0,6 0 0 1 -1 0\n8,5 -1 8 2 0 -1\n 1 -1 8 1 0 0\n0,1 -1 -9 2 0 0\n 0 1 0 0 0 0", 4: " 1 0 1 -8 0 -2 0 0 0 0\n 28 0 2 8 0 -2 0 0 0 0\n 42 0 1 -6 0 1 0 0 0 0\n 1 0 0 1 0 0 0 0 0 0\n 0,6 0 0 0 0 1 0 -1 0 0\n 8,5 0 -1 8 0 2 0 0 0 -1\n 1 0 -1 8 0 1 0 0 0 0\n 0,1 0 -1 -9 0 2 0 0 0 0\n 1 1 -8 0 -2 0 0 0 0 0\n 700 2 8 0 -2 0 0 0 0 0\n1050 1 -6 0 1 0 0 0 0 0\n 0,6 0 0 0 1 0 -1 0 0 0\n 8,5 -1 8 0 2 0 0 0 -1 0\n 1 -1 8 0 1 0 0 0 0 0\n 0,1 -1 -9 0 2 0 0 0 0 0\n 0 0 1 0 0 0 0 0 0 0", 5: "-2 -2 1 0 0 -1\n 1 -1 -2 0 0 -2\n-5 0 0 1 -1 -1\n 1 0 0 -1 1 -2\n 0 -4 -6 -2 -2 -4", 6: "0 -2 -9 1 9\n0 1/3 1 -1/3 -2\n1 1 1 1 1\n0 2 3 -1 -12", 7: "-4 -2 -1 0 0\n-6 1 -2 0 0\n-2 0 0 1 -1\n-2 0 0 -1 1\n-4 -1 -2 -1 -2\n 0 -2 1 -5 1", 8: " 4 1 1 -1\n -4 -1 -1 -1\n-0,5 -1 -1 0\n 3 -1 0 0\n 3 0 -1 0\n 3 0 0 -1\n 0 1 2 1", 9: " 5 1 0 0 0 0 0 0 0\n 25 4 1 0 0 0 0 0 0\n 125 8 4 1 0 0 0 0 0\n 625 16 8 4 1 0 0 0 0\n 3125 32 16 8 4 1 0 0 0\n 15625 64 32 16 8 4 1 0 0\n 78125 128 64 32 16 8 4 1 0\n390625 256 128 64 32 16 8 4 1\n 0 128 64 32 16 8 4 2 1", 10: " 1 1 0 0 0 0 0 0 0\n 100 20 1 0 0 0 0 0 0\n 10000 200 20 1 0 0 0 0 0\n 1000000 2000 200 20 1 0 0 0 0\n 100000000 20000 2000 200 20 1 0 0 0\n 10000000000 200000 20000 2000 200 20 1 0 0\n 1000000000000 2000000 200000 20000 2000 200 20 1 0\n100000000000000 20000000 2000000 200000 20000 2000 200 20 1\n 0 10000000 1000000 100000 10000 1000 100 10 1" }; function debounce(fn, ms) { var t = 0; return function () { var args = arguments; clearTimeout(t); t = setTimeout(function () { fn.apply(null, args); }, ms || 150); }; } function cloneRat(r) { return new Rat(r.n, r.d); } function deepCloneMatrix(M) { var R = new Array(M.length); for (var ii = 0; ii < M.length; ii++) { R[ii] = new Array(M[ii].length); for (var jj = 0; jj < M[ii].length; jj++) R[ii][jj] = cloneRat(M[ii][jj]); } return R; } function decimal(val) { return val.toDecimal(16).replace(/\./, ",").toUpperCase(); } function format(val) { var arg = String(val).replace(/\./, ",").toUpperCase(); return (arg.length > 2 && arg.indexOf("/1") == arg.length - 2) ? arg.substr(0, arg.length - 2) : arg; } var SPACE_CACHE = " ".repeat(512); function space(val) { val = Math.max(0, Math.min(val, 512)); return SPACE_CACHE.substr(0, val); } function finite() { return solve = true; } function updateThumb(slider, thumbId) { const thumb = document.getElementById(thumbId); const percent = (slider.value - slider.min) / (slider.max - slider.min); const sliderWidth = slider.offsetWidth || 260; const thumbWidth = thumb.offsetWidth || 24; const x = percent * (sliderWidth - thumbWidth) + thumbWidth / 2; thumb.style.left = x + "px"; thumb.textContent = slider.value; } function matrixToText(M) { var mm = M.length, nn = M[0].length, out = ""; var len = new Array(nn), maxs = new Array(nn), maxv, mem; for (j = 0; j < nn; j++) { len[j] = new Array(mm); maxv = 0; for (i = 0; i < mm; i++) { mem = format(M[i][j]).length; if (mem > maxv) maxv = mem; len[j][i] = mem; } maxs[j] = maxv + 1; } for (i = 1; i < mm; i++) { for (j = 0; j < nn; j++) out += space(maxs[j] - len[j][i]) + format(M[i][j]); out += "\n"; } for (j = 0; j < nn; j++) out += space(maxs[j] - len[j][0]) + format(M[0][j]); return out; } function parseTextMatrix(input) { input = (input || "").trim(); var rest = input.replace(/[\d\-\/,eE\.\s+]/g, ""); if (rest !== "") throw new Error("Es sind unzulässige Zeichen enthalten."); input = input.replace(/,/g, ".").replace(/[\r]/g, "").replace(/[ \t]+$/gm, ""); var rows = input.split(/\n+/).filter(function (x) { return x.trim() !== ""; }); if (rows.length < 2) throw new Error("Es sind mindestens zwei Zeilen erforderlich."); var raw = new Array(rows.length); var rex = /([+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?(?:\/[+\-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+\-]?\d+)?)?|[+\-]?\d+(?:[eE][+\-]?\d+)?(?:\/\d+(?:[eE][+\-]?\d+)?)?)/g; var cols = 0; for (var r = 0; r < rows.length; r++) { var toks = rows[r].match(rex); if (!toks || toks.length < 2) throw new Error("Die Eingabe ist nicht ausreichend oder nicht zulässig."); if (r === 0) cols = toks.length; if (toks.length !== cols) throw new Error("Die Matrix hat in Zeile " + (r + 1) + " leider " + toks.length + " Spalten statt " + cols + "."); raw[r] = new Array(cols); for (var c = 0; c < cols; c++) raw[r][c] = bigRat(toks[c]); } var M = new Array(rows.length); M[0] = raw[rows.length - 1]; for (var rr = 0; rr < rows.length - 1; rr++) M[rr + 1] = raw[rr]; return M; } function setSourceMatrix(M) { sourceState.matrix = deepCloneMatrix(M); sourceState.text = matrixToText(M); document.ratplex.data.value = sourceState.text; } function setSourceText(text) { var M = parseTextMatrix(text); setSourceMatrix(M); } function makeRandomMatrix(mm, nn) { var M = new Array(mm); for (var ii = 0; ii < mm; ii++) { M[ii] = new Array(nn); for (var jj = 0; jj < nn; jj++) { var x = Math.random(); var v = (x > 0.5) ? Math.round(FACTOR * x) : -Math.round(FACTOR * x); M[ii][jj] = bigRat(v); } M[ii][0] = M[ii][0].abs(); } M[0][0] = ZERO; return M; } function random(renderOnly) { m = parseInt(document.ratplex.m.value, 10); n = parseInt(document.ratplex.n.value, 10); document.ratplex.x.selectedIndex = 0; setSourceMatrix(makeRandomMatrix(m, n)); if (renderOnly !== false) compute(); } function check() { try { var txt = document.ratplex.data.value; if (sourceState.matrix && txt === sourceState.text) { a = deepCloneMatrix(sourceState.matrix); } else { a = parseTextMatrix(txt); sourceState.matrix = deepCloneMatrix(a); sourceState.text = txt; } m = a.length; n = a[0].length; if (m < 2 || n < 2) { alert("Es sind mindestens zwei Zeilen und mindestens zwei Spalten erforderlich."); return false; } if (finite()) return true; } catch (err) { alert(err.message || String(err)); return false; } return false; } function redundant() { var test; for (i = 1; i < m; i++) { test = bv[i]; if (mbv[test]) { for (j = 1; j < n && a[i][j].leq(ZERO); j++); if (j == n) { mbv[test] = false; if (test < ns) cn++; else cb++; } } } } function trans(row, col) { k = row; l = col; solve = false; tableau("", 2, true); str += "Die Rechengrenze wurde überschritten.\n"; } function norm_scale() { var minv, obj, sca; if (nor1 || nor2) { if (output) str += "Die 1. Normierung wird durchgeführt.\n"; for (i = 1; i < m; i++) { sca = ZERO; for (j = 1; j < n; j++) sca = sca.add(a[i][j].times(a[i][j])); sca = bigRat(Math.sqrt(sca.toNumber() || 0)); if (sca.eq(ZERO)) sca = bigRat(1); for (j = 0; j < n; j++) a[i][j] = a[i][j].divide(sca); n1[i] = sca.reciprocate(); } } if (scal) { if (output) str += "Die Skalierung wird durchgeführt.\n"; for (j = 1; j < n; j++) { minv = INFINITY; for (i = 1; i < m; i++) { obj = a[i][j].abs(); if (obj.gt(ZERO) && obj.lt(minv)) minv = obj; } minv = minv.reciprocate(); for (i = 0; i < m; i++) a[i][j] = a[i][j].times(minv); e[tab[j]] = minv; } if (nor1 && nor2) { if (output) str += "Die 2. Normierung wird durchgeführt.\n"; for (i = 1; i < m; i++) { sca = ZERO; for (j = 1; j < n; j++) sca = sca.add(a[i][j].times(a[i][j])); sca = bigRat(Math.sqrt(sca.toNumber() || 0)); if (sca.eq(ZERO)) sca = bigRat(1); for (j = 0; j < n; j++) a[i][j] = a[i][j].divide(sca); n2[i] = sca.reciprocate(); } } } } function pivot(inc, mem, v) { var ele = a[0][v], dif, pro, quo, sca, sum; switch (rule) { case 1: sum = bigRat(1); for (i = 1; i < m; i++) sum = sum.add(a[i][v].times(a[i][v])); pro = ele.times(ele); quo = pro.divide(sum); if (quo.gt(max)) { k = mem; l = v; max = quo; } else if (quo.eq(max)) { pro = ele.times(inc); if (pro.gt(bet)) { k = mem; l = v; bet = pro; } } break; case 2: pro = ele.times(inc); if (pro.gt(max)) { k = mem; l = v; max = pro; } else if (pro.eq(max)) { sum = bigRat(1); for (i = 1; i < m; i++) sum = sum.add(a[i][v].times(a[i][v])); pro = ele.times(ele); quo = pro.divide(sum); if (quo.gt(bet)) { k = mem; l = v; bet = quo; } } break; case 3: quo = ele.divide(a[mem][v]); sum = quo; sca = quo.times(quo); for (j = 1; j < n; j++) { pro = a[mem][j].times(quo); dif = a[0][j].subtract(pro); sum = sum.add(dif); pro = dif.times(dif); sca = sca.add(pro); } sum = sum.times(sum.abs()); quo = sum.divide(sca); if (quo.lt(min)) { k = mem; l = v; min = quo; } else if (quo.eq(min)) { pro = ele.times(inc); if (pro.gt(max)) { k = mem; l = v; max = pro; } } break; } } var scratchPline = []; function transform(val) { var rowel, pivotv = a[k][l].reciprocate(), ak = a[k], i, j, r; a[k][l] = pivotv; rowel = pivotv.times(ak[0]).negate(); if (val == 0) { for (i = 0; i < k; i++) a[i][0] = a[i][0].add(rowel.times(a[i][l])); for (i = k + 1; i < m; i++) a[i][0] = a[i][0].add(rowel.times(a[i][l])); } else { for (i = 0; i < val; i++) { r = s[i]; a[r][0] = a[r][0].add(rowel.times(a[r][l])); } } ak[0] = rowel.negate(); scratchPline.length = n; for (j = 1; j < l; j++) { scratchPline[j] = ak[j]; ak[j] = pivotv.times(ak[j]); } for (j = l + 1; j < n; j++) { scratchPline[j] = ak[j]; ak[j] = pivotv.times(ak[j]); } pivotv = pivotv.negate(); for (i = 0; i < k; i++) { a[i][l] = pivotv.times(a[i][l]); rowel = a[i][l]; for (j = 1; j < l; j++) a[i][j] = a[i][j].add(rowel.times(scratchPline[j])); for (j = l + 1; j < n; j++) a[i][j] = a[i][j].add(rowel.times(scratchPline[j])); } for (i = k + 1; i < m; i++) { a[i][l] = pivotv.times(a[i][l]); rowel = a[i][l]; for (j = 1; j < l; j++) a[i][j] = a[i][j].add(rowel.times(scratchPline[j])); for (j = l + 1; j < n; j++) a[i][j] = a[i][j].add(rowel.times(scratchPline[j])); } if ((red || few)) redundant(); } function tableau(string, piv, force) { if (!force && !output) { str += string; return; } var i, j, len = [], maxs = [], nbvl = [], maxw = TAB, mem; if (opt == 1) a[0][0] = a[0][0].negate(); str += string; len[n] = new Array(m); nbvl[n] = maxw; for (i = 1; i < m; i++) { mem = String(bv[i]).length; if (mem > maxw) maxw = mem; len[n][i] = mem; } maxs[n] = ++maxw; if (l > 0) { len[0] = new Array(m); maxw = TAB; nbvl[0] = maxw; for (i = 0; i < m; i++) { tmp = a[i][0]; mem = format(tmp).length; if (mem > maxw) maxw = mem; len[0][i] = mem; } maxs[0] = ++maxw; } else { len[0] = new Array(m); maxs[0] = TAB + 1; nbvl[0] = TAB; for (i = 0; i < m; i++) len[0][i] = format(a[i][0]).length; } for (j = 1; j < l; j++) { len[j] = new Array(m); maxw = String(nbv[j]).length; nbvl[j] = maxw; for (i = 0; i < m; i++) { tmp = a[i][j]; mem = format(tmp).length; if (mem > maxw) maxw = mem; len[j][i] = mem; } maxs[j] = ++maxw; } len[l] = new Array(m); maxw = l > 0 ? String(nbv[l]).length : TAB; nbvl[l] = maxw; for (i = 0; i < k; i++) { tmp = a[i][l]; mem = format(tmp).length; if (mem > maxw) maxw = mem; len[l][i] = mem; } tmp = a[k] && a[k][l] ? a[k][l] : ZERO; mem = format(tmp).length + piv; if (mem > maxw) maxw = mem; len[l][k] = mem; for (i = k + 1; i < m; i++) { tmp = a[i][l]; mem = format(tmp).length; if (mem > maxw) maxw = mem; len[l][i] = mem; } maxs[l] = ++maxw; for (j = l + 1; j < n; j++) { len[j] = new Array(m); maxw = String(nbv[j]).length; nbvl[j] = maxw; for (i = 0; i < m; i++) { tmp = a[i][j]; mem = format(tmp).length; if (mem > maxw) maxw = mem; len[j][i] = mem; } maxs[j] = ++maxw; } str += space(maxs[n] - TAB) + " BV:"; str += space(maxs[0] - TAB) + "RS\\NBV:"; for (j = 1; j < n; j++) str += space(maxs[j] - nbvl[j]) + nbv[j]; str += "\n"; for (i = 1; i < k; i++) { str += space(maxs[n] - len[n][i]) + bv[i]; for (j = 0; j < n; j++) str += space(maxs[j] - len[j][i]) + format(a[i][j]); str += "\n"; } if (k > 0) { str += space(maxs[n] - len[n][k]) + bv[k]; for (j = 0; j < l; j++) str += space(maxs[j] - len[j][k]) + format(a[k][j]); str += (piv == 2) ? space(maxs[l] - len[l][k]) + "»" + format(a[k][l]) + "«" : space(maxs[l] - len[l][k]) + format(a[k][l]); for (j = l + 1; j < n; j++) str += space(maxs[j] - len[j][k]) + format(a[k][j]); str += "\n"; } for (i = k + 1; i < m; i++) { str += space(maxs[n] - len[n][i]) + bv[i]; for (j = 0; j < n; j++) str += space(maxs[j] - len[j][i]) + format(a[i][j]); str += "\n"; } str += (prog == 1) ? ((opt == 1) ? space(maxs[n] - TAB) + "PP Max:" : space(maxs[n] - TAB) + "PP Min:") : ((opt == 1) ? space(maxs[n] - TAB) + "DP Min:" : space(maxs[n] - TAB) + "DP Max:"); for (j = 0; j < l; j++) str += space(maxs[j] - len[j][0]) + format(a[0][j]); str += (piv == 2 && k == 0) ? space(maxs[l] - len[l][0]) + "»" + format(a[0][l]) + "«" : space(maxs[l] - len[l][0]) + format(a[0][l]); for (j = l + 1; j < n; j++) str += space(maxs[j] - len[j][0]) + format(a[0][j]); str += "\n"; if (opt == 1) a[0][0] = a[0][0].negate(); } function loop(last) { var t = [], u = [], o, p, q, r, v, ele, inc, man, mem, per, pro, quo, sca; l = 0; nul = 0; do { k = 0; q = 0; for (j = 1; j < n; j++) if (a[0][j].gt(ZERO)) u[q++] = j; if (q > 0) { o = 0; bet = ZERO; max = ZERO; pro = ZERO; min = INFINITY; if (nul == 0) { p = 0; for (i = 1; i < m; i++) if (a[i][0].eq(ZERO)) s[o++] = i; else t[p++] = i; } else { for (i = 1; i < m; i++) if (a[i][0].eq(ZERO)) o++; } if (o > 0 || nul > 0) { if (nul == 0) nul = o; if (o > 0) { for (i = 0; i < nul && solve; i++) { sca = ZERO; r = s[i]; for (j = 1; j < n; j++) sca = sca.add(a[r][j].times(a[r][j])); a[r][0] = a[r][0].add(bigRat(Math.sqrt(sca.toNumber() || 0))); } } for (j = 0; j < q; j++) { v = u[j]; for (i = 0; i < nul && a[s[i]][v].leq(ZERO); i++); if (i == nul) { inc = INFINITY; for (i = 0; i < p; i++) { r = t[i]; ele = a[r][v]; if (ele.gt(ZERO)) { quo = a[r][0].divide(ele); if (quo.lt(inc)) { inc = quo; mem = r; } } } if (inc.lt(INFINITY)) pivot(inc, mem, v); } } if (k > 0) { for (i = 0; i < nul; i++) a[s[i]][0] = ZERO; nul = 0; } } else { for (j = 0; j < q; j++) { v = u[j]; inc = INFINITY; for (i = 1; i < m; i++) { ele = a[i][v]; if (ele.gt(ZERO)) { quo = a[i][0].divide(ele); if (quo.lt(inc)) { inc = quo; mem = i; } } } if (inc.lt(INFINITY)) pivot(inc, mem, v); } } if (nul > 0) { bet = ZERO; max = ZERO; min = INFINITY; for (j = 0; j < q; j++) { v = u[j]; inc = INFINITY; for (i = 0; i < nul; i++) { r = s[i]; ele = a[r][v]; if (ele.gt(ZERO)) { quo = a[r][0].divide(ele); if (quo.lt(inc)) { inc = quo; mem = r; } } } if (inc.lt(INFINITY)) pivot(inc, mem, v); } per = (k > 0) ? ++perts : false; } else per = false; if (k > 0) { mem = bv[k]; bv[k] = nbv[l]; nbv[l] = mem; steps++; if (output) { tableau("", 2); str += "Das Pivotelement ist a[" + k + "][" + (l + 1) + "] = " + format(a[k][l]) + ".\n"; if (per) str += "Eine Perturbation war erforderlich.\n"; } man = a[0][0]; transform(nul); if (last && a[0][0].neq(man)) return; if (!solve) { trans(i, j); k = 0; } } } } while (k > 0); if (nul > 0 && solve) { if (output) tableau("", 0); for (i = 0; i < nul; i++) a[s[i]][0] = ZERO; if (output) str += "Tableau ohne Perturbationen:\n"; } } function numbers(string) { if (steps == 1) str += "Es wurden" + string + " ein Pivotschritt und "; else str += "Es wurden" + string + " " + steps + " Pivotschritte und "; if (perts == 0) str += "keine Perturbationen benötigt.\n"; else str += (perts == 1) ? "eine Perturbation benötigt.\n" : perts + " Perturbationen benötigt.\n"; } function compute() { var t0 = performance.now(); function results() { var br = new Array(ms - 1), ng = []; numbers(""); if (prog == 1) str += (opt == 1) ? "Das Maximum liegt bei " + format(a[0][0].negate()) + " (" + decimal(a[0][0].negate()) + ")." : "Das Minimum liegt bei " + format(a[0][0]) + " (" + decimal(a[0][0]) + ")."; else str += (opt == 1) ? "Das Minimum liegt bei " + format(a[0][0].negate()) + " (" + decimal(a[0][0].negate()) + ")." : "Das Maximum liegt bei " + format(a[0][0]) + " (" + decimal(a[0][0]) + ")."; for (j = 1; j < ns; j++) x[j] = ZERO; for (i = 1; i < ms; i++) { y[i] = ZERO; if (bv[i] < ns) x[bv[i]] = a[i][0]; } if (scal) for (j = 1; j < n; j++) x[tab[j]] = x[tab[j]].times(e[tab[j]]); if (few && ble) { for (i = m; i < ms; i++) { bv[i] -= ns - 1; br[i] = b[bv[i]][0]; for (j = 1; j < ns; j++) br[i] = br[i].subtract(b[bv[i]][j].times(x[j])); ng[i] = br[i].lt(ZERO); } for (j = n; j < ns; j++) { min = ZERO; for (i = m; i < ms; i++) { if (ng[i] && b[bv[i]][nbv[j]].lt(ZERO)) { tmp = br[i].divide(b[bv[i]][nbv[j]]); if (tmp.gt(min)) { min = tmp; ng[i] = false; } } } x[nbv[j]] = min; } for (i = m; i < ms; i++) bv[i] += ns - 1; } str += (prog == 1) ? "\n1. primale rationale Lösung: " : "\n1. duale rationale Lösung: "; for (j = 1; j < ns; j++) { str += format(x[j]) + " "; if (nbv[j] >= ns) y[nbv[j] - ns + 1] = a[0][j].negate(); } str += (prog == 1) ? "\n1. primale Fließkommalösung: " : "\n1. duale Fließkommalösung: "; for (j = 1; j < ns; j++) str += decimal(x[j]) + " "; if (nor1 || nor2) for (i = 1; i < m; i++) y[i] = y[i].times(n1[i]); if (nor1 && scal && nor2) for (i = 1; i < m; i++) y[i] = y[i].times(n2[i]); if (ms == 1) { str += (prog == 1) ? "\n1. duale rationale Lösung: Existiert nicht.\n1. duale Fließkommalösung: Existiert nicht." : "\n1. primale rationale Lösung: Existiert nicht.\n1. primale Fließkommalösung: Existiert nicht."; } else { str += (prog == 1) ? "\n1. duale rationale Lösung: " : "\n1. primale rationale Lösung: "; for (i = 1; i < ms; i++) str += format(y[i]) + " "; str += (prog == 1) ? "\n1. duale Fließkommalösung: " : "\n1. primale Fließkommalösung: "; for (i = 1; i < ms; i++) str += decimal(y[i]) + " "; } str += (m < ms || less) ? "\nDie Restriktionsanzahl wurde verringert.\n" : "\n"; } var index = document.ratplex.x.selectedIndex; if (index > 0 && (!sourceState.matrix || document.ratplex.data.value !== sourceState.text)) { try { setSourceText(EXAMPLES[index]); } catch (_) {} } str = ""; if (check()) { k = 0; l = 0; opt = Number(document.querySelector('input[name="opt"]:checked').value); op = Number(document.querySelector('input[name="op"]:checked').value); prog = Number(document.querySelector('input[name="prog"]:checked').value); if (opt == 1) a[0][0] = a[0][0].negate(); else for (j = 1; j < n; j++) a[0][j] = a[0][j].negate(); if (op == 2) for (i = 1; i < m; i++) for (j = 0; j < n; j++) a[i][j] = a[i][j].negate(); if (prog == 2) { opt = (opt == 1) ? 2 : 1; min = Math.min(m, n); for (i = 0; i < min; i++) { for (j = 0; j <= i; j++) { tmp = a[i][j]; a[i][j] = a[j][i].negate(); a[j][i] = tmp.negate(); } } if (m != n) { if (m < n) { for (j = m; j < n; j++) { a[j] = new Array(m); for (i = 0; i < m; i++) a[j][i] = a[i][j].negate(); } } else { for (i = n; i < m; i++) for (j = 0; j < n; j++) a[j][i] = a[i][j].negate(); } tmp = m; m = n; n = tmp; } } for (j = 1; j < n; j++) nbv[j] = j; for (i = 1; i < m; i++) bv[i] = n + i - 1; str += "Das lineare Programm hat " + m + " Zeilen und " + n + " Spalten.\n"; for (i = 1; i < m && solve; i++) { for (j = 1; j < n && a[i][j].geq(ZERO); j++); if (j == n && a[i][0].lt(ZERO)) { k = i; solve = false; tableau("", 2, true); str += "Das lineare Programm ist nicht lösbar.\n"; } } var abs, ele, f = [], g = [], ar = [], cj = 0, eq = [], le = [], h, hco, hgi, hli, heq, hsi, hge, hle, ind, leng = [], maxs = [], lco, lgi, lli, llim, lsi, mem, none = true, one, q = 0, r, ri = 0, sca, too, ulim; red = document.ratplex.red.checked; few = document.ratplex.few.checked; less = false; if (red || few) { b[0] = []; for (j = 0; j < n; j++) b[0][j] = a[0][j]; for (i = 1; i < m; i++) { b[i] = []; b[i][0] = a[i][0]; max = ZERO; sca = ZERO; for (j = 1; j < n; j++) { b[i][j] = a[i][j]; abs = b[i][j].abs(); if (abs.gt(max)) max = abs; } max = (max.eq(ZERO)) ? bigRat(1) : max.reciprocate(); b[i][0] = b[i][0].times(max); for (j = 1; j < n; j++) { b[i][j] = b[i][j].times(max); sca = sca.add(b[i][j].times(b[i][j])); } sca = (sca.gt(ZERO)) ? bigRat(1 / Math.sqrt(sca.toNumber() || 1)) : bigRat(1); for (j = 0; j < n; j++) b[i][j] = b[i][j].times(sca); f[i] = b[i][0].geq(ZERO); if (f[i]) { for (j = 1; j < n && b[i][j].leq(ZERO); j++); f[i] = j == n; } } if (m > 2) { for (i = 1; i < m; i++) { hsi = b[i][0]; hgi = hsi.gt(ZERO); hli = hsi.lt(ZERO); hge = hsi.geq(ZERO); hle = hsi.leq(ZERO); heq = hsi.eq(ZERO); for (k = i + 1; !f[i] && k < m; k++) { if (!f[k]) { lsi = b[k][0]; if (hle && lsi.geq(ZERO)) l = i; else if (hge && lsi.leq(ZERO)) l = k; else l = 0; h = (l == i) ? k : i; if (l != 0) { llim = ZERO; ulim = INFINITY; } else { l = k; if (hgi) { llim = ZERO; ulim = hsi.divide(lsi); } else { llim = hsi.divide(lsi); ulim = INFINITY; } } one = true; for (j = 1; one && j < n; j++) { hco = b[h][j]; lco = b[l][j]; var hgo = hco.gt(ZERO), hlo = hco.lt(ZERO), lgo = lco.gt(ZERO), llo = lco.lt(ZERO); if ((hgo && lgo) || (hlo && llo)) { hco = hco.divide(lco); if (lgo && llim.lt(hco)) llim = hco; else if (llo && ulim.gt(hco)) ulim = hco; if (llim.gt(ulim.add(EPSILON))) one = false; } else { if (hgo && lco.leq(ZERO)) one = false; else if (hco.geq(ZERO) && llo) one = false; } } f[h] = one; if (!one && ((hgi && lsi.gt(ZERO)) || (hli && lsi.lt(ZERO)) || (heq && lsi.eq(ZERO)))) { llim = (hli) ? lsi.divide(hsi) : ZERO; ulim = (hgi) ? lsi.divide(hsi) : INFINITY; one = true; for (j = 1; one && j < n; j++) { hco = b[h][j]; lco = b[l][j]; var hgo2 = hco.gt(ZERO), hlo2 = hco.lt(ZERO), lgo2 = lco.gt(ZERO), llo2 = lco.lt(ZERO); if ((hgo2 && lgo2) || (hlo2 && llo2)) { lco = lco.divide(hco); if (hgo2 && llim.lt(lco)) llim = lco; else if (hlo2 && ulim.gt(lco)) ulim = lco; if (llim.gt(ulim.add(EPSILON))) one = false; } else { if (hlo2 && lco.leq(ZERO)) one = false; else if (hco.leq(ZERO) && lgo2) one = false; } } f[l] = one; } } } } } for (i = 1; i < m; i++) if (f[i]) g[q++] = i; if (q > 0) { str += (q == 1) ? "Folgende Zeile ist" : "Folgende Zeilen sind"; str += " überflüssig:\n"; for (j = 0; j < n; j++) { leng[j] = new Array(q); max = 0; for (i = 0; i < q; i++) { tmp = a[g[i]][j]; mem = format(tmp).length; if (mem > max) max = mem; leng[j][i] = mem; } maxs[j] = ++max; } for (i = 0; i < q; i++) { ind = g[i]; for (j = 0; j < n; j++) str += space(maxs[j] - leng[j][i]) + format(a[ind][j]); str += "\n"; } q = 1; for (i = 1; i < m; i++) { if (!f[i]) { for (j = 0; j < n; j++) a[q][j] = a[i][j]; q++; } } m = q; less = true; } cb = 0; cn = 0; for (i = 0; i < m + n - 1; i++) mbv[i] = true; } ms = m; ns = n; beq = false; ble = false; for (i = 1; i < m; i++) ar[i] = false; for (j = 1; j < n; j++) { eq[j] = a[0][j].eq(ZERO); if (eq[j]) { for (i = 1; i < m && a[i][j].eq(ZERO); i++); eq[j] = i == m; if (eq[j] && !beq) beq = cj = j; else { for (i = 1; i < m && a[i][j].leq(ZERO); i++); le[j] = i == m; if (le[j]) { if (!ble) ble = cj = j; for (i = 1; i < m; i++) if (a[i][j].lt(ZERO)) ar[i] = true; } } } } if (few) { if (ble || beq) { q = 1; r = n; for (j = 1; j < n; j++) { if (le[j] || eq[j]) { r--; for (i = 0; i < m; i++) b[i][r] = a[i][j]; nbv[r] = j; } else { for (i = 0; i < m; i++) a[i][q] = a[i][j]; tab[q] = j; nbv[q++] = j; } } for (j = r; j < n; j++) for (i = 0; i < m; i++) a[i][j] = b[i][j]; n = q; nbv[0] = 0; if (ble) { q = 1; r = ms; for (i = 1; i < ms; i++) { if (ar[i]) { r--; for (j = 0; j < ns; j++) b[r][j] = a[i][j]; bv[r] = i + ns - 1; } else { for (j = 0; j < ns; j++) a[q][j] = a[i][j]; bv[q++] = i + ns - 1; } } for (i = r; i < ms; i++) for (j = 0; j < ns; j++) a[i][j] = b[i][j]; m = q; } q = ns - 1; for (i = 1; i < ms; i++) for (j = 0; j < ns; j++) b[bv[i] - q][nbv[j]] = bigRat(a[i][j]); } else { for (i = 1; i < m; i++) for (j = 0; j < n; j++) b[i][j] = a[i][j]; for (j = 1; j < n; j++) tab[j] = j; } } else { for (j = 1; j < n; j++) tab[j] = j; } for (i = 1; i < m && ri == 0; i++) { if (a[i][0].eq(ZERO)) { for (j = 1; j < n && a[i][j].geq(ZERO); j++); if (j == n) ri = i; } } if (solve) { var allp = 0, alls = 0, c = new Array(n), index2, limit = true, p = n, u = new Array(n), v = new Array(m), w = new Array(n), min0 = ZERO, hadPhase1 = false, obj, x = new Array(ns - 1), y = new Array(ms - 1); ind = 0; mem = a[0][0]; for (j = 1; j < n && limit; j++) { if (a[0][j].gt(ZERO)) { for (i = 1; i < m && a[i][j].lt(ZERO); i++); limit = i < m; } } if (limit && m > 1) { rule = Number(document.querySelector('input[name="rule"]:checked').value); output = document.ratplex.output.checked; nor1 = document.ratplex.nor1.checked; scal = document.ratplex.scal.checked; nor2 = document.ratplex.nor2.checked; perts = 0; steps = 0; min0 = ZERO; for (i = 1; i < m; i++) { ele = a[i][0]; if (ele.lt(min0)) { k = i; min0 = ele; } } if (min0.lt(ZERO)) { hadPhase1 = true; l = 0; if (output) tableau("", 0); norm_scale(); for (i = 1; i < m; i++) a[i][n] = bigRat(-1); for (j = 1; j < n; j++) { c[j] = a[0][j]; a[0][j] = ZERO; none &= c[j].eq(ZERO); } nbv[n] = bv[k]; bv[k] = 0; a[0][0] = ZERO; c[0] = ZERO; a[0][n] = bigRat(-1); l = n++; steps++; if (output) { tableau("Phase I:\n", 2); str += "Das Pivotelement ist a[" + k + "][" + (l + 1) + "] = -1/1.\n"; } transform(0); if (solve) { index2 = k; loop(false); if (solve) { if (a[0][0].abs().gt(EPSILON)) { solve = false; k = 0; l = 0; tableau("", 2, true); str += "Das lineare Programm ist nicht lösbar.\n"; numbers(""); } else { k = index2; if (output) tableau("", 0); if (nbv[l] != 0) { for (l = n - 1; l > 0 && a[k][l].eq(ZERO); l--); bv[k] = nbv[l]; nbv[l] = 0; steps++; transform(0); if (output) tableau("Das Pivotelement ist a[" + k + "][" + (l + 1) + "] = " + format(a[k][l].reciprocate()) + ".\n", 2); } if (solve) { phase1 = false; n--; if (nbv[l] == 0 && l < n) { for (i = 1; i < m; i++) a[i][l] = a[i][n]; nbv[l] = nbv[n]; } a[0][0] = mem; if (none) { l = 0; if (output) tableau("Ende Phase I:\n", 0); results(); } else { none = false; for (j = 1; j < n; j++) { l = nbv[j]; a[0][j] = (l < ns) ? c[l] : ZERO; } for (i = 1; i < m; i++) { l = bv[i]; if (l < ns) { obj = c[l].negate(); for (j = 0; j < n; j++) a[0][j] = a[0][j].add(obj.times(a[i][j])); } } for (j = 0; j < n; j++) if (a[0][j].abs().lt(EPSILON)) a[0][j] = ZERO; if (red || few) redundant(); if (output) str += "Ende Phase I:\n"; } } else { str += "Die Rechengrenze wurde überschritten.\n"; numbers(""); } } } else numbers(""); } else { str += "Die Rechengrenze wurde überschritten.\n"; numbers(""); } } else { none = false; k = 0; l = 0; if (output && (nor1 || nor2 || scal)) tableau("", 0); norm_scale(); } if (solve && !none) { phase1 = false; for (j = 1; j < n && a[0][j].leq(ZERO); j++); if (j < n) { if (hadPhase1) { if (output) { numbers(""); str += "Phase II:\n"; } allp = perts; alls = steps; perts = 0; steps = 0; } loop(false); if (solve) { for (j = 1; j < n && a[0][j].leq(ZERO); j++); if (j < n) { solve = false; l = j; tableau("", 2, true); str += "Das lineare Programm ist unbeschränkt in Spalte " + (++j) + ".\n"; numbers(""); } else { if (output) tableau("", 0); results(); } } else numbers(""); if (hadPhase1) { perts += allp; steps += alls; numbers(" insgesamt"); } } else { k = 0; l = 0; if (output) tableau("", 0); results(); } } } else { if (m > 1 && !limit) { solve = false; k = 0; l = j - 1; tableau("", 2, true); str += "Das lineare Programm ist unbeschränkt in Spalte " + j + ".\n"; } if (prog == 2) opt = (opt == 1) ? 2 : 1; } } if (red || few) { if (m == 1) { for (j = 1; j < n && a[0][j].eq(ZERO); j++); if (j < n && a[0][j].gt(ZERO)) { solve = false; k = 0; l = j; tableau("", 2, true); str += "Das lineare Programm ist unbeschränkt in Spalte " + j + ".\n"; } else { k = 0; l = 0; perts = 0; steps = 0; if (output) tableau("", 0); results(); } } m = ms; n = ns; if (cb > 0) { too = (q > 0) ? " ebenfalls" : ""; str += (cb == 1) ? "Folgende Zeile ist" : "Folgende Zeilen sind"; str += too + " überflüssig:\n"; for (j = 0; j < n; j++) { leng[j] = new Array(m); max = 0; for (i = 1; i < m; i++) { tmp = b[i][j]; mem = format(tmp).length; if (mem > max) max = mem; leng[j][i] = mem; } maxs[j] = ++max; } for (i = 1; i < m; i++) if (!mbv[i + n - 1]) { for (j = 0; j < n; j++) str += space(maxs[j] - leng[j][i]) + format(b[i][j]); str += "\n"; } } if (!mbv[0]) cn--; if (cn > 0) { str += (cn == 1) ? "Folgende Variable bedarf" : "Folgende Variablen bedürfen"; str += " keiner Nichtnegativitätsbedingung:\n"; for (j = 1; j < n; j++) if (!mbv[j]) str += j + " "; str += "\n"; } } if (solve) { q = 0; mem = a[0][0]; for (i = 1; i < m; i++) { if (a[i][0].eq(ZERO)) { v[++q] = bv[i]; for (j = 1; j < n; j++) b[q][j] = a[i][j]; } } l = 0; for (j = 1; j < n; j++) { u[j] = a[0][j]; w[j] = nbv[j]; if (u[j].eq(ZERO)) { if (j > ++l) { nbv[l] = nbv[j]; for (i = 1; i < m; i++) a[i][l] = a[i][j]; } a[0][l] = bigRat(1); } } if (ble || beq) { none = false; l = 0; x[cj] = x[cj].add(bigRat(1)); } else none = true; if (l > 0) { n = ++l; none = red; output = false; red = false; loop(true); red = none; none = mem.eq(a[0][0]); for (j = 1; j < n && (a[0][j].leq(ZERO) || nbv[j] >= ns); j++); for (i = 1; i < ns; i++) x[i] = ZERO; for (i = 1; i < ms; i++) if (bv[i] < ns) x[bv[i]] = a[i][0]; if (scal) for (i = 1; i < ns; i++) x[tab[i]] = x[tab[i]].times(e[tab[i]]); if (none && j < n) none = !decimal(x[nbv[j]] = bigRat(1)); } if (none) { str += (prog == 1) ? "2. primale rationale Lösung: Existiert nicht.\n2. primale Fließkommalösung: Existiert nicht." : "2. duale rationale Lösung: Existiert nicht.\n2. duale Fließkommalösung: Existiert nicht."; } else { str += (prog == 1) ? "2. primale rationale Lösung: " : "2. duale rationale Lösung: "; for (j = 1; j < ns; j++) str += format(x[j]) + " "; str += (prog == 1) ? "\n2. primale Fließkommalösung: " : "\n2. duale Fließkommalösung: "; for (j = 1; j < ns; j++) str += decimal(x[j]) + " "; } if (ri > 0) { none = false; q = 0; y[ri] = y[ri].add(bigRat(1)); } else none = true; if (q > 0) { m = p; n = ++q; a = new Array(m); a[0] = new Array(n); a[0][0] = mem; for (i = 1; i < m; i++) { a[i] = new Array(n); a[i][0] = u[i].negate(); bv[i] = w[i]; for (j = 1; j < n; j++) a[i][j] = b[j][i].negate(); } for (j = 1; j < n; j++) { nbv[j] = v[j]; a[0][j] = bigRat(1); } none = red; output = false; red = false; loop(true); red = none; none = mem.eq(a[0][0]); for (i = 1; i < ms; i++) y[i] = ZERO; for (j = 1; j < n && (a[0][j].leq(ZERO) || nbv[j] < ns); j++); for (i = 1; i < m; i++) if (bv[i] >= ns) y[bv[i] - ns + 1] = a[i][0]; if (nor1 || nor2) for (i = 1; i < ms; i++) y[i] = y[i].times(n1[i]); if (nor1 && scal && nor2) for (i = 1; i < ms; i++) y[i] = y[i].times(n2[i]); if (none && j < n) none = !decimal(y[nbv[j] - ns + 1] = bigRat(1)); } if (none) { str += (prog == 1) ? "\n2. duale rationale Lösung: Existiert nicht.\n2. duale Fließkommalösung: Existiert nicht." : "\n2. primale rationale Lösung: Existiert nicht.\n2. primale Fließkommalösung: Existiert nicht."; } else { str += (prog == 1) ? "\n2. duale rationale Lösung: " : "\n2. primale rationale Lösung: "; for (i = 1; i < ms; i++) str += format(y[i]) + " "; str += (prog == 1) ? "\n2. duale Fließkommalösung: " : "\n2. primale Fließkommalösung: "; for (i = 1; i < ms; i++) str += decimal(y[i]) + " "; } } } document.ratplex.result.value = str; document.getElementById("runtime").textContent = "Laufzeit: " + (performance.now() - t0).toFixed(1) + " ms"; } window.compute = compute; window.random = random; window.updateThumb = updateThumb; window.initBhDeMinplex = initMinplex; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initMinplex); } else { initMinplex(); } })();