Skip to content

Commit

Permalink
refactor .spy views, unbind free variables from axes and visualize no…
Browse files Browse the repository at this point in the history
… intersections on no solutions
  • Loading branch information
menocsk27 committed Nov 28, 2024
1 parent 4721b76 commit 2006e74
Show file tree
Hide file tree
Showing 30 changed files with 81 additions and 252 deletions.
129 changes: 33 additions & 96 deletions frontend/public/js/proof/rules/cd/linear/linear.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const tip = {
const premiseColor = '#80cbc4';
const conclusionColor = '#b89aef';
const plot = 'cd-linear-plot';
const eval_tolerance = 0.001;

let struct = {}; // copy of the node/subproof data
let vars = []; // list of variables. The order of this list determines the order of the solutions, which allows us to "target" which variables will be free in case of infinite solutions.
Expand Down Expand Up @@ -192,19 +193,12 @@ function vis(plot, solution) {
container.appendChild(vis);
}

vis.innerHTML =
`<div id=${plot}> </div>
vis.innerHTML = `<div id=${plot}> </div>`;

<div id="${plot}-noSolutionPreviewContainer" style="display: none;">
<div style="text-align:center">
<h2>The System Has No Solution</h2>
<span>Augmented Matrix:</span>
<div id="${plot}-initialStatePreview" class="preview"></div>
<span>Echelon Form:</span>
<div id="${plot}-finalStatePreview" class="preview"></div>
</div>
</div>`;
return visByType(solution);
}

function visByType(solution) {
switch (solution.type) {
case 'unique solution':
return visualizeUniqueSolution(plot, solution);
Expand Down Expand Up @@ -264,7 +258,9 @@ function visualizeUniqueSolution(plot, _data) {
annotations.push({ x: eval(f(v)), color });
hl[id] = {
svg: () => document.querySelectorAll(`#${plot} .annotations path`)[annotations.length-1],
evaluate: point => Fraction(v).equals(Fraction(point.x)),
evaluate: point =>
Fraction(v).gt(Fraction(point.x - eval_tolerance)) &&
Fraction(v).lt(Fraction(point.x + eval_tolerance)),
color
};
annots += 1;
Expand All @@ -279,7 +275,7 @@ function visualizeUniqueSolution(plot, _data) {
const p = Fraction(independentTerm).mul(Fraction(point.x));
const s = Fraction(c).sub(p);
const d = s.div(Fraction(dependentCoefficient));
return d.equals(Fraction(point.y));
return d.gt(Fraction(point.y - eval_tolerance)) && d.lt(Fraction(point.y + eval_tolerance));
},
color
};
Expand Down Expand Up @@ -405,8 +401,11 @@ function visualizeInfiniteSolutions(plot, _data) {
}
}

const x = { varName: vars[0], fn: dependentValues[vars[0]] };
const y = { varName: vars[1], fn: dependentValues[vars[1]] };
const select1 = document.querySelector(`#var1`);
const select2 = document.querySelector(`#var2`);

const x = { varName: select1.value, fn: dependentValues[select1.value] || independent[select1.value]};
const y = { varName: select2.value, fn: dependentValues[select2.value] || independent[select2.value] };

const annotations = [
{ x: eval(f(x.fn)), text: `${x.varName} = ${f(x.fn)}` },
Expand Down Expand Up @@ -457,24 +456,27 @@ function visualizeInfiniteSolutions(plot, _data) {
annotations.push({ x: eval(f(v)), text: `${x.varName} = ${f(v)}`, color });
hl[id] = {
svg: () => document.querySelectorAll(`#${plot} .annotations path`)[annotations.length-1],
evaluate: point => Fraction(v).equals(Fraction(point.x)),
evaluate: point =>
Fraction(v).gt(Fraction(point.x - eval_tolerance)) &&
Fraction(v).lt(Fraction(point.x + eval_tolerance)),
color
};
annots += 1;
} else {
console.error('both of the selected variables canceled');
console.log(row.map(r => f(r)))
console.log('both of the selected variables canceled -- no intersection');
}
} else {
data.push({ fn: equation, color, updateOnMouseMove: false, graphType: 'polyline' });
hl[id] = {
color,
svg: () => document.querySelectorAll(`#${plot} .graph path.line`)[Math.max(0, i - annots)],
evaluate: (point) => {
const p = Fraction(independentCoef).mul(Fraction(point.x)).add(Fraction(replacedSum));
const s = Fraction(constantTerm).sub(p);
const d = s.div(Fraction(dependentCoef));
return d.equals(Fraction(point.y));
},
color
return d.gt(Fraction(point.y - eval_tolerance)) && d.lt(Fraction(point.y + eval_tolerance));
}
};
}
}
Expand Down Expand Up @@ -503,34 +505,8 @@ function visualizeInfiniteSolutions(plot, _data) {
return { plot: p, hl };
}

function visualizeNoSolutions(plot, data) {
const initialStatePreview = document.getElementById(`${plot}-initialStatePreview`);
const finalStatePreview = document.getElementById(`${plot}-finalStatePreview`);
const noSolutionPreviewContainer = document.getElementById(`${plot}-noSolutionPreviewContainer`);

// Function to render matrix using KaTeX
function renderMatrixKaTeX(matrix, container) {
let matrixString = '\\begin{bmatrix}';
matrix.forEach((row, idx) => {
matrixString += row.slice(0, -1).map(coef => f(coef)).join(' & ');
matrixString += ' & \\vert & ' + f(row[row.length - 1]); // Adds the augmented column
if (idx < matrix.length - 1) matrixString += ' \\\\ ';
});
matrixString += '\\end{bmatrix}';

// Clear previous content and render new matrix
container.innerHTML = '';
katex.render(matrixString, container, { throwOnError: false, displayMode: true });
}

// Render initial and final state matrices
renderMatrixKaTeX(data.matrix.slice(0, data.matrix.length - 1), initialStatePreview);
renderMatrixKaTeX(data.echelon, finalStatePreview);

// Show the preview container
noSolutionPreviewContainer.style = 'display:block';

return {};
function visualizeNoSolutions(plot, _data) {
visualizeInfiniteSolutions(plot, _data);
}

export class LinearCD {
Expand Down Expand Up @@ -571,17 +547,8 @@ export class LinearCD {
}
});

switch (data.type) {
case 'unique solution':
return visualizeUniqueSolution(plot, data);
case 'infinite solutions':
vars = [select1.value, select2.value, ...vars.filter(v => v !== select1.value && v !== select2.value)];
const solution = solve(struct);
createSliders(solution);
return visualizeInfiniteSolutions(plot, solution);
case 'no solution':
return visualizeNoSolutions(plot, solution);
}
const solution = solve(struct);
visByType(solution);
}

select1.onchange = update;
Expand All @@ -590,6 +557,8 @@ export class LinearCD {
}

function createSliders(data) {
if (data.free <= 0) { return; }

frees = [];
const freeVarsContainer = document.getElementById(`slidersContainer`);
freeVarsContainer.innerHTML = '<div>Free Variables:</div>';
Expand Down Expand Up @@ -635,52 +604,28 @@ export class LinearCD {

// interaction
select.onchange = (d) => {
const select1 = document.getElementById(`var1`);
const select2 = document.getElementById(`var2`);
const idx = +d.target.id.split('select-free-')[1];
const previous = frees[idx]

let replaced = '';
if (d.target.value === select1.value) {
select1.value = previous;
replaced = 'var1'
}

if (d.target.value === select2.value) {
select2.value = previous;
replaced = 'var2'
}

if (replaced !== '') {
const other = replaced === "var1" ? `#var2 option` : `#var1 option`;
document.querySelectorAll(other).forEach(opt => {
opt.disabled = false;
if (opt.value === document.getElementById(replaced).value) {
opt.disabled = true;
}
});

}

for (let i = 0; i < frees.length; i++) {
if (frees[i] === d.target.value && i !== idx) {
frees[i] = previous;
}
}

frees[idx] = d.target.value;
const deps = vars.filter(v => v !== select1.value && v !== select2.value && !frees.includes(v));
vars = [select1.value, select2.value, ...deps, ...frees];
const comp = vars.filter(v => !frees.includes(v));
vars = [...comp, ...frees];
const solution = solve(struct);
createSliders(solution);
return visualizeInfiniteSolutions(plot, solution);
visByType(solution);
}

slider.oninput = () => {
sliders[varName] = parseFloat(slider.value);
label.textContent = `${varName}: ${slider.value}`;
document.getElementById(`sol-${varName}`).innerHTML = `${varName} = ${slider.value}`;
visualizeInfiniteSolutions(plot, data);
visByType(data);
};

sliders[varName] = parseFloat(slider.value);
Expand Down Expand Up @@ -711,15 +656,7 @@ export class LinearCD {
</div>`;

generateVariableSelectors(data);

switch (data.type) {
case 'infinite solutions':
createSliders(data);
break;
case 'no solution':
console.log(data.free);
break;
}
createSliders(data);
}

draw(data, params, where) {
Expand Down
3 changes: 3 additions & 0 deletions frontend/public/style/colors.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
--color-teal-dark: #36afa3;
--color-teal-darker: #3ca096;
--color-gray-light: #eceff1;
--color-gray-lighter: #fafafa;
--color-gray: #b0bec5;
--color-gray-dark: #9e9e9e;
--color-gray-darker:#757575;
--color-lime-light: #f0f4c3;
--color-lime: #cddc39;


}
2 changes: 1 addition & 1 deletion frontend/public/style/inference.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "./nodes.css";
/* uses colors from @import "./nodes.css"; */

#inference-view {
width: 100%;
Expand Down
6 changes: 3 additions & 3 deletions frontend/public/style/ontology.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "./nodes.css";
/* uses colors from @import "./nodes.css"; */

:root {
--color-node-fill: hsl(205, 87%, 94%);
Expand Down Expand Up @@ -110,14 +110,14 @@ input:checked + .slider:before {

border: 2px solid transparent;
border-radius: 4px;
background-color: #fafafa;
background-color: var(--color-gray-lighter);
text-align: left;
cursor: pointer;
font-size: 12px;
font-weight: lighter;
}
.repair-entry:focus {
background-color: #fafafa;
background-color: var(--color-gray-lighter);;
border: 2px solid #efefef;
}
.repair-entry.locked > .lock-sign {
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/style/proof.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "./nodes.css";
/* uses colors from @import "./nodes.css"; */

:root {
--color-conn-rule: var(--color-gray);
Expand Down
8 changes: 4 additions & 4 deletions frontend/public/style/widgets/explanation.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
@import "../colors.css";
/* uses colors from @import "../colors.css"; */

.explanation-popover {
position: absolute;
display: inline-block;
height: fit-content;
background-color: #fafafa;
background-color: var(--color-gray-lighter);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2);
}

.explanation-container {
display: block;
width: 100%;
background-color: var(--color-gray-light);
background-color: var(--color-gray-lighter);
text-align: justify !important;
}

Expand Down Expand Up @@ -43,7 +43,7 @@
}

.explanation-popover>.popoverText {
background-color: #fafafa;
background-color: var(--color-gray-lighter);
color: black;
text-align: center;
border-radius: 2px;
Expand Down
2 changes: 2 additions & 0 deletions frontend/public/style/widgets/general.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* single point of entry to load styles - do not duplicate @imports in other .css files! */
@import "../colors.css";
@import "../nodes.css";
@import "explanation.css";
@import "minimap.css";
@import "sidebar.css";
Expand Down
12 changes: 0 additions & 12 deletions frontend/views/defs.spy

This file was deleted.

4 changes: 2 additions & 2 deletions frontend/views/euler/euler.spy
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

<body>

<< menus/menu >>
<< widgets/menus/menu >>

<main id="euler-container">
<div id="euler-view"></div>

<< menus/thumbnail >>
<< widgets/menus/thumbnail >>
</main>

<< scripts >>
Expand Down
4 changes: 2 additions & 2 deletions frontend/views/inference/inference.spy
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<body>

<< menus/menu >>
<< widgets/menus/menu >>

<main id="inference-container">
<div id="inference-view">
Expand All @@ -25,7 +25,7 @@
</div>


<< menus/thumbnail >>
<< widgets/menus/thumbnail >>
</main>

<< scripts >>
Expand Down
Loading

0 comments on commit 2006e74

Please sign in to comment.