Created
June 20, 2024 21:59
-
-
Save ingenieroariel/c6366fd4c54f42e73a9d8d97b8e36d5f to your computer and use it in GitHub Desktop.
Revisions
-
ingenieroariel created this gist
Jun 20, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,351 @@ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Improved Interaction Combinators Visualization</title> <style> canvas { border: 1px solid black; } #controls { margin-top: 10px; } button { margin-right: 10px; } #debug { margin-top: 10px; font-family: monospace; white-space: pre; } </style> </head> <body> <canvas id="icCanvas" width="800" height="600"></canvas> <div id="controls"> <button id="stepBtn">Step</button> <button id="resetBtn">Reset</button> </div> <div id="debug"></div> <script type="module"> const canvas = document.getElementById('icCanvas'); const adapter = await navigator.gpu.requestAdapter(); const device = await adapter.requestDevice(); const context = canvas.getContext('webgpu'); const format = navigator.gpu.getPreferredCanvasFormat(); context.configure({ device: device, format: format, }); const shader = device.createShaderModule({ code: ` struct VertexOutput { @builtin(position) position: vec4f, @location(0) color: vec4f, }; @vertex fn vertexMain(@location(0) position: vec2f, @location(1) color: vec4f) -> VertexOutput { var output: VertexOutput; output.position = vec4f(position, 0.0, 1.0); output.color = color; return output; } @fragment fn fragmentMain(input: VertexOutput) -> @location(0) vec4f { return input.color; } ` }); const pipeline = device.createRenderPipeline({ layout: 'auto', vertex: { module: shader, entryPoint: 'vertexMain', buffers: [{ arrayStride: 24, attributes: [ { shaderLocation: 0, offset: 0, format: 'float32x2' }, { shaderLocation: 1, offset: 8, format: 'float32x4' }, ], }], }, fragment: { module: shader, entryPoint: 'fragmentMain', targets: [{ format: format }], }, }); const CellType = { CONSTRUCTOR: 0, DUPLICATOR: 1, ERASER: 2, }; class Cell { constructor(type, x, y) { this.type = type; this.x = x; this.y = y; this.ports = [null, null, null]; // principal, aux1, aux2 } } class Connection { constructor(fromCell, fromPort, toCell, toPort) { this.fromCell = fromCell; this.fromPort = fromPort; this.toCell = toCell; this.toPort = toPort; } } let cells = []; let connections = []; function createInitialConfiguration() { cells = [ new Cell(CellType.CONSTRUCTOR, -0.5, 0.5), new Cell(CellType.CONSTRUCTOR, 0.5, 0.5), new Cell(CellType.ERASER, 0, -0.5) ]; connections = [ new Connection(cells[0], 0, cells[1], 0), new Connection(cells[0], 1, cells[2], 0), new Connection(cells[1], 2, cells[2], 0) ]; updateCellConnections(); } function updateCellConnections() { for (let cell of cells) { cell.ports = [null, null, null]; } for (let conn of connections) { conn.fromCell.ports[conn.fromPort] = { cell: conn.toCell, port: conn.toPort }; conn.toCell.ports[conn.toPort] = { cell: conn.fromCell, port: conn.fromPort }; } } function step() { for (let i = 0; i < cells.length; i++) { for (let j = i + 1; j < cells.length; j++) { if (areConnectedByPrincipalPorts(cells[i], cells[j])) { applyInteractionRule(cells[i], cells[j]); return true; } } } return false; } function areConnectedByPrincipalPorts(cell1, cell2) { return cell1.ports[0] && cell1.ports[0].cell === cell2 && cell1.ports[0].port === 0; } function applyInteractionRule(cell1, cell2) { if (cell1.type === CellType.CONSTRUCTOR && cell2.type === CellType.CONSTRUCTOR) { // γγ rule let aux1Cell1 = cell1.ports[1] ? cell1.ports[1].cell : null; let aux1Port1 = cell1.ports[1] ? cell1.ports[1].port : null; let aux2Cell1 = cell1.ports[2] ? cell1.ports[2].cell : null; let aux2Port1 = cell1.ports[2] ? cell1.ports[2].port : null; let aux1Cell2 = cell2.ports[1] ? cell2.ports[1].cell : null; let aux1Port2 = cell2.ports[1] ? cell2.ports[1].port : null; let aux2Cell2 = cell2.ports[2] ? cell2.ports[2].cell : null; let aux2Port2 = cell2.ports[2] ? cell2.ports[2].port : null; // Connect the auxiliary ports of the cells that were connected to the constructors if (aux1Cell1 && aux1Cell2) { connect(aux1Cell1, aux1Port1, aux1Cell2, aux1Port2); } if (aux2Cell1 && aux2Cell2) { connect(aux2Cell1, aux2Port1, aux2Cell2, aux2Port2); } // Remove the interacting cells cells = cells.filter(c => c !== cell1 && c !== cell2); connections = connections.filter(conn => conn.fromCell !== cell1 && conn.fromCell !== cell2 && conn.toCell !== cell1 && conn.toCell !== cell2 ); updateCellConnections(); } // Add other rules as needed } function connect(cell1, port1, cell2, port2) { if (!cell1 || !cell2) return; // Remove any existing connections for these ports connections = connections.filter(conn => !(conn.fromCell === cell1 && conn.fromPort === port1) && !(conn.fromCell === cell2 && conn.fromPort === port2) && !(conn.toCell === cell1 && conn.toPort === port1) && !(conn.toCell === cell2 && conn.toPort === port2) ); // Add the new connection connections.push(new Connection(cell1, port1, cell2, port2)); } function render() { const vertexData = []; const indexData = []; let vertexCount = 0; // Operation: Render cells for (let cell of cells) { const cellSize = 0.05; const x = cell.x; const y = cell.y; let color; switch (cell.type) { case CellType.CONSTRUCTOR: color = [1, 0, 0, 1]; // Red break; case CellType.DUPLICATOR: color = [0, 1, 0, 1]; // Green break; case CellType.ERASER: color = [0, 0, 1, 1]; // Blue break; } vertexData.push( x - cellSize, y - cellSize, ...color, x + cellSize, y - cellSize, ...color, x + cellSize, y + cellSize, ...color, x - cellSize, y + cellSize, ...color ); indexData.push( vertexCount, vertexCount + 1, vertexCount + 2, vertexCount, vertexCount + 2, vertexCount + 3 ); vertexCount += 4; } // Operation: Render connections for (let conn of connections) { const fromX = conn.fromCell.x; const fromY = conn.fromCell.y; const toX = conn.toCell.x; const toY = conn.toCell.y; const lineWidth = 0.005; const dx = toX - fromX; const dy = toY - fromY; const length = Math.sqrt(dx * dx + dy * dy); const nx = -dy / length * lineWidth; const ny = dx / length * lineWidth; vertexData.push( fromX + nx, fromY + ny, 0, 0, 0, 1, fromX - nx, fromY - ny, 0, 0, 0, 1, toX + nx, toY + ny, 0, 0, 0, 1, toX - nx, toY - ny, 0, 0, 0, 1 ); indexData.push( vertexCount, vertexCount + 1, vertexCount + 2, vertexCount + 1, vertexCount + 2, vertexCount + 3 ); vertexCount += 4; } // Operation: Create and populate buffers const vertexBuffer = device.createBuffer({ size: vertexData.length * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, }); const indexBuffer = device.createBuffer({ size: indexData.length * 2, usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST, }); device.queue.writeBuffer(vertexBuffer, 0, new Float32Array(vertexData)); device.queue.writeBuffer(indexBuffer, 0, new Uint16Array(indexData)); // Operation: Encode and submit commands const commandEncoder = device.createCommandEncoder(); const textureView = context.getCurrentTexture().createView(); const renderPass = commandEncoder.beginRenderPass({ colorAttachments: [{ view: textureView, clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }, loadOp: 'clear', storeOp: 'store', }], }); renderPass.setPipeline(pipeline); renderPass.setVertexBuffer(0, vertexBuffer); renderPass.setIndexBuffer(indexBuffer, 'uint16'); renderPass.drawIndexed(indexData.length); renderPass.end(); device.queue.submit([commandEncoder.finish()]); } function debugPrint() { let output = "Cells:\n"; cells.forEach((cell, index) => { output += `Cell ${index}: Type=${cell.type}, Pos=(${cell.x}, ${cell.y})\n`; cell.ports.forEach((port, portIndex) => { if (port) { output += ` Port ${portIndex}: Connected to Cell ${cells.indexOf(port.cell)}, Port ${port.port}\n`; } else { output += ` Port ${portIndex}: Not connected\n`; } }); }); output += "\nConnections:\n"; connections.forEach((conn, index) => { output += `Connection ${index}: Cell ${cells.indexOf(conn.fromCell)} Port ${conn.fromPort} -> Cell ${cells.indexOf(conn.toCell)} Port ${conn.toPort}\n`; }); document.getElementById('debug').textContent = output; } createInitialConfiguration(); render(); debugPrint(); const stepBtn = document.getElementById('stepBtn'); const resetBtn = document.getElementById('resetBtn'); stepBtn.addEventListener('click', () => { if (step()) { render(); debugPrint(); console.log("Step applied successfully."); } else { console.log("No more reductions possible."); } }); resetBtn.addEventListener('click', () => { createInitialConfiguration(); render(); debugPrint(); }); </script> </body> </html>