Skip to content

Instantly share code, notes, and snippets.

@flisboac
Created October 19, 2020 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flisboac/689d7b30398d8e54bba2013b149d3c76 to your computer and use it in GitHub Desktop.
Save flisboac/689d7b30398d8e54bba2013b149d3c76 to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
</head>
<body>
<div id="options">
<label for="cellSize">Cell size</label>
<input type="number" id="cellSize" name="cellSize" min="10" max="9999" step="5" value="20">
<label for="nvars">Number of variables</label>
<input type="number" id="nvars" name="nvars" min="1" max="9999" step="1" value="0">
<input type="checkbox" name="enableK" id="enableK">
<label for="k">k</label>
<input type="number" id="k" name="k" min="0" max="9999" step="2" value="0">
<label for="l">l</label>
<input type="number" id="l" name="l" min="0" max="9999" step="2" value="0">
<label for="algorithmChoice">Algorithm</label>
<select id="algorithmChoice" name="algorithmChoice">
<optgroup label="Operators' dependencies">
<option value="close">Close/Strong-close</option>
<option value="addConsIteration">Add Constraint (Float, Iteration cell)</option>
<option value="addConsInsert">Add Constraint (Float, Inserted cell)</option>
<option value="addConsStrongCloseIteration">Add Constraint & Strong-Close (Float, Iteration cell)</option>
<option value="addConsStrongCloseInsert">Add Constraint & Strong-Close (Float, Inserted cell)</option>
</optgroup>
<optgroup label="Matrix sections">
<option value="counterpart">Counterpart (Coherency)</option>
<option value="consistencyCells">Consistency cells</option>
<option value="unaryConsCells">Unary-cons cells</option>
<option value="binaryConsCells">Binary-cons cells</option>
<option value="halfMatrixCells">Half-matrix cells</option>
</optgroup>
</select>
</div>
<hr>
<div id="info">
<span>Info:</span>
<label for="nHighlightedCells">Qty. Highligted</label>
<input type="text" id="nHighlightedCells" name="nHighlightedCells" readonly style="width: 5em">
</div>
<div id="counts">
<span>Cell counts (compact mode):</span>
<label for="nConsistencyCells">Consistency</label>
<input type="text" id="nConsistencyCells" name="nConsistencyCells" readonly style="width: 5em">
<label for="nUnaryConsCells">Unary-cons</label>
<input type="text" id="nUnaryConsCells" name="nUnaryConsCells" readonly style="width: 5em">
<label for="nBinaryConsCells">Binary-cons</label>
<input type="text" id="nBinaryConsCells" name="nBinaryConsCells" readonly style="width: 5em">
<label for="nTotalCells">Total</label>
<input type="text" id="nTotalCells" name="nTotalCells" readonly style="width: 5em">
</div>
<hr>
<svg id="repr"></svg>
</body>
<style>
body {
font-size: 12px;
}
</style>
<script>
const config = { cellWidth: 10, cellHeight: 10};
const model = {
get k() { return document.getElementById("enableK").checked ? parseInt($('#k').val()) : null; },
get l() { return document.getElementById("enableK").checked ? parseInt($('#l').val()) : null; },
get fontSize() { return parseInt(this.cellSize) * 0.50; },
get cellSize() { return parseInt($('#cellSize').val()); },
get cellWidth() { return this.cellSize; },
get cellHeight() { return this.cellSize; },
get octsize() { return parseInt($('#nvars').val()); },
get diffsize() { return parseInt($('#nvars').val()) * 2; },
get algorithm() { return $('#algorithmChoice').val(); },
get nRoundedConsistencyCells() { return this.octsize % 2 == 0 ? this.octsize : this.octsize + 1; },
get nConsistencyCells() { return this.octsize; },
get nUnaryConsCells() { return this.diffsize; },
get nBinaryConsCells() {
const calculate = (x) => x <= 0 ? 0 : calculate(x - 1) + (x - 1);
return calculate(this.octsize) * 4;
}
};
const cells = d3.select("#repr");
$('#nvars').on('change', () => resizeCells());
$('#cellSize').on('change', () => resizeCells());
$('#fontSize').on('change', () => resizeCells());
function resizeCells() {
cells
.attr('width', model.cellWidth * (model.diffsize + 1))
.attr('height', model.cellHeight * (model.diffsize + 1))
.selectAll('*')
.remove();
for (let i = 0; i < model.diffsize; i++) {
createHeaderCell(0, i + 1, `x${i}`);
createHeaderCell(i + 1, 0, `x${i}`);
}
for (let index of indexes()) {
cells
.append('rect')
.datum(index)
.attr('id', (datum) => `cell_${datum.xi}_${datum.xj}`)
.attr("x", (datum) => (datum.xi + 1) * model.cellWidth)
.attr("y", (datum) => (datum.xj + 1) * model.cellHeight)
.attr('class', 'cell')
.attr("height", model.cellHeight)
.attr("width", model.cellWidth)
.attr("fill", "#7d777b")
.attr("stroke", "#efefef")
.text((datum) => `${datum.xi},${datum.xj}`)
.style("text-anchor", 'middle')
.on("mouseover", highlightCell)
.on("mouseout", unhighlightCell)
;
}
$('#nConsistencyCells').val(`${model.nConsistencyCells} (${model.nRoundedConsistencyCells})`);
$('#nUnaryConsCells').val(model.nUnaryConsCells);
$('#nBinaryConsCells').val(model.nBinaryConsCells);
$('#nTotalCells').val(
`${
model.nConsistencyCells + model.nUnaryConsCells + model.nBinaryConsCells
} (${
model.nRoundedConsistencyCells + model.nUnaryConsCells + model.nBinaryConsCells
})`);
}
function createHeaderCell(i, j, text, attrs) {
let x = i * model.cellWidth;
let y = j * model.cellHeight;
let groupElem = cells
.append('g')
.attr('class', 'header_cell')
.attr("transform", (d, i) => `translate(${x}, ${y})`)
.attr('width', model.cellWidth)
.attr('height', model.cellHeight);
let textElem = groupElem
.append('text')
.attr('x', model.cellWidth / 2)
.attr('y', model.cellHeight / 2)
.attr('font-size', model.fontSize)
.style('alignment-baseline', 'central')
.style("text-anchor", 'middle')
.style("font-weight", 'bold')
.text(text);
}
function highlightCell(datum, dataIndex, elem) {
let coords = generateHighlightCoordinates(datum);
this.setAttribute('stroke', '#ff0000');
cells
.selectAll(`#cell_${negate(datum.xj)}_${negate(datum.xi)}`)
.attr("stroke", '#ff0000')
;
for (let coord of coords) {
let cell = cells
.selectAll(`#cell_${coord[0]}_${coord[1]}`)
.attr('fill', coord[2] || '#ada7ab')
;
}
$('#nHighlightedCells').val(`${coords.size} (${coords.size / 2})`)
}
function unhighlightCell(datum, dataIndex, elem) {
cells
.selectAll('.cell')
.attr("stroke", "#efefef")
.attr("fill", "#7d777b")
;
$('#nHighlightedCells').val(0)
}
function generateHighlightCoordinates(datum) {
let coords = new Set();
let i = datum.xi;
let j = datum.xj;
let I = negate(i);
let J = negate(j);
function counterpart() {
coords.add([i, j]).add([J, I]);
}
function consistencyCells() {
for (let i = 0; i < model.diffsize; i = i + 2) {
let I = negate(i);
coords.add([i, i, '#eda7ab']).add([I, I, '#ada7ab']);
}
}
function unaryConsCells() {
for (let i = 0; i < model.diffsize; i = i + 2) {
let I = negate(i);
coords.add([i, I, '#eda7ab']).add([I, i, '#eda7ab']);
}
}
function binaryConsCells() {
for (let i = 0; i < model.diffsize; i = i + 1) {
let I = negate(i);
for (let j = 0; j < I; j = j + 1) {
let J = negate(j);
if (i != j) {
coords.add([i, j, '#ada7ab']).add([J, I, '#eda7ab']);
}
}
}
}
function halfMatrixCells() {
consistencyCells();
unaryConsCells();
binaryConsCells();
}
function addCons(mode) {
function genCoords(k, l) {
let i, j, a, b;
if (mode === 'insertion') {
a = datum.xi;
b = datum.xj;
i = k;
j = l;
} else {
i = datum.xi;
j = datum.xj;
a = k;
b = l;
}
let I = negate(i);
let J = negate(j);
let A = negate(a);
let B = negate(b);
// coords
// .add([i, I, '#eda7ab'])
// .add([i, a, '#ada7ab']).add([b, I, '#ada7ab'])
// .add([i, B, '#9da7ab']).add([A, a, '#9da7ab']).add([b, I, '#9da7ab'])
// .add([i, a, '#8da7ab']).add([b, B, '#8da7ab']).add([A, I, '#8da7ab'])
// ;
coords
.add([i, j, '#eda7ab'])
.add([i, a, '#ada7ab']).add([b, j, '#ada7ab'])
.add([i, B, '#9da7ab']).add([A, j, '#9da7ab'])
.add([i, B, '#8da7ab']).add([A, a, '#8da7ab']).add([b, j, '#8da7ab'])
.add([i, a, '#7da7ab']).add([b, B, '#7da7ab']).add([A, j, '#7da7ab'])
.add([i, I, '#dda7ab']).add([J, j, '#dda7db'])
;
}
let hasK = typeof model.k === 'number';
let hasL = typeof model.l === 'number';
if (hasK && hasL) {
genCoords(model.k, model.l);
} else {
for (let k = 0; k < model.octsize; k = k + 2) {
for (let l = 0; l < model.octsize; l = l + 2) {
genCoords(k, l);
}
}
}
}
function addConsStrongClose(mode) {
function genCoords(k, l) {
let i, j, a, b;
if (mode === 'insertion') {
a = datum.xi;
b = datum.xj;
i = k;
j = l;
} else {
i = datum.xi;
j = datum.xj;
a = k;
b = l;
}
let I = negate(i);
let J = negate(j);
let A = negate(a);
let B = negate(b);
// coords
// .add([i, I, '#eda7ab'])
// .add([i, a, '#ada7ab']).add([b, I, '#ada7ab'])
// .add([i, B, '#9da7ab']).add([A, a, '#9da7ab']).add([b, I, '#9da7ab'])
// .add([i, a, '#8da7ab']).add([b, B, '#8da7ab']).add([A, I, '#8da7ab'])
// ;
coords
.add([i, I, '#fda7ab'])
.add([i, a, '#ada7ab']).add([b, I, '#ada7ab'])
.add([i, B, '#9da7ab']).add([A, I, '#9da7ab'])
.add([i, B, '#8da7ab']).add([A, a, '#8da7ab']).add([b, I, '#8da7ab'])
.add([i, a, '#7da7ab']).add([b, B, '#7da7ab']).add([A, I, '#7da7ab'])
.add([i, j, '#fda7ab'])
.add([i, a, '#ada7ab']).add([b, j, '#ada7ab'])
.add([i, B, '#9da7ab']).add([A, j, '#9da7ab'])
.add([i, B, '#8da7ab']).add([A, a, '#8da7ab']).add([b, j, '#8da7ab'])
.add([i, a, '#7da7ab']).add([b, B, '#7da7ab']).add([A, j, '#7da7ab'])
.add([i, I, '#dda7ab']).add([J, j, '#dda7db'])
;
}
let hasK = typeof model.k === 'number';
let hasL = typeof model.l === 'number';
if (hasK && hasL) {
genCoords(model.k, model.l);
} else {
for (let k = 0; k < model.octsize; k = k + 2) {
for (let l = 0; l < model.octsize; l = l + 2) {
genCoords(k, l);
}
}
}
}
function close() {
const genCoords = (k) => {
let K = k + 1;
coords
.add([k, K])
.add([K, k])
.add([i, k])
.add([i, K])
.add([k, j])
.add([K, j])
;
};
coords.add([i, j]);
if (typeof model.k === 'number') {
genCoords(model.k);
} else {
for (let k = 0; k < model.octsize; k = k + 2) genCoords(k);
}
}
switch(model.algorithm) {
case 'close': close(); break;
case 'counterpart': counterpart(); break;
case 'consistencyCells': consistencyCells(); break;
case 'unaryConsCells': unaryConsCells(); break;
case 'binaryConsCells': binaryConsCells(); break;
case 'halfMatrixCells': halfMatrixCells(); break;
case 'addConsIteration': addCons('iteration'); break;
case 'addConsInsert': addCons('insertion'); break;
case 'addConsStrongCloseIteration': addConsStrongClose('iteration'); break;
case 'addConsStrongCloseInsert': addConsStrongClose('insertion'); break;
}
return coords;
}
function *indexes(test) {
for (let xi = 0; xi < model.diffsize; xi++) {
for (let xj = 0; xj < model.diffsize; xj++) {
let f = (test ? test(xi, xj) : null);
yield { xi, xj, test: f };
}
}
}
function negate(v) {
return v % 2 === 0 ? v + 1 : v - 1;
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment