Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '26'
cache: 'npm'

- name: Install dependencies
Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
26
184 changes: 92 additions & 92 deletions components/Quantum/QuantumCircuitVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,112 +102,112 @@ export default function QuantumCircuitVisualizer({ circuit }) {
}));
}

function drawCircuit(c) {
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();

const spacingX = 80;
const spacingY = 60;
const maxTime = getMaxTime(c);
const width = maxTime * spacingX + 200;
const height = c.qubits * spacingY + 120;

svg.attr("viewBox", `0 0 ${width} ${height}`).style("width", svgWidth);

for (let t = 0; t <= maxTime; t++) {
const x = 100 + spacingX * t;
svg.append("text").attr("x", x).attr("y", 20).text(`t=${t}`);
svg
.append("line")
.attr("x1", x)
.attr("x2", x)
.attr("y1", 30)
.attr("y2", height - 30)
.attr("stroke", "#ddd")
.attr("stroke-dasharray", "4 4");
}

[...Array(c.qubits).keys()].forEach((q) => {
const y = 60 + q * spacingY;

svg.append("text").attr("x", 20).attr("y", y + 5).text(`q${q}`);

svg
.append("line")
.attr("x1", 60)
.attr("x2", width - 30)
.attr("y1", y)
.attr("y2", y)
.attr("stroke", "#222")
.attr("stroke-width", 2);
});

c.gates.forEach((g) => {
const x = 100 + g.t * spacingX;

if (g.type === "h" || g.type === "x") {
const y = 60 + g.qubit * spacingY;
svg
.append("rect")
.attr("x", x - 20)
.attr("y", y - 20)
.attr("width", 40)
.attr("height", 40)
.attr("fill", "white")
.attr("stroke", "black");
useEffect(() => {
function drawCircuit(c) {
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();

svg
.append("text")
.attr("x", x)
.attr("y", y + 5)
.attr("text-anchor", "middle")
.attr("font-weight", "bold")
.text(g.type.toUpperCase());
}
const spacingX = 80;
const spacingY = 60;
const maxTime = getMaxTime(c);
const width = maxTime * spacingX + 200;
const height = c.qubits * spacingY + 120;

if (g.type === "cnot") {
const yC = 60 + g.control * spacingY;
const yT = 60 + g.target * spacingY;
svg.attr("viewBox", `0 0 ${width} ${height}`).style("width", svgWidth);

svg.append("circle").attr("cx", x).attr("cy", yC).attr("r", 7).attr("fill", "black");
for (let t = 0; t <= maxTime; t++) {
const x = 100 + spacingX * t;
svg.append("text").attr("x", x).attr("y", 20).text(`t=${t}`);
svg
.append("line")
.attr("x1", x)
.attr("x2", x)
.attr("y1", yC)
.attr("y2", yT)
.attr("stroke", "black");
.attr("y1", 30)
.attr("y2", height - 30)
.attr("stroke", "#ddd")
.attr("stroke-dasharray", "4 4");
}

svg
.append("circle")
.attr("cx", x)
.attr("cy", yT)
.attr("r", 12)
.attr("stroke", "black")
.attr("fill", "white");
[...Array(c.qubits).keys()].forEach((q) => {
const y = 60 + q * spacingY;

svg
.append("line")
.attr("x1", x - 8)
.attr("x2", x + 8)
.attr("y1", yT)
.attr("y2", yT)
.attr("stroke", "black");
svg.append("text").attr("x", 20).attr("y", y + 5).text(`q${q}`);

svg
.append("line")
.attr("x1", x)
.attr("x2", x)
.attr("y1", yT - 8)
.attr("y2", yT + 8)
.attr("stroke", "black");
}
});
}
.attr("x1", 60)
.attr("x2", width - 30)
.attr("y1", y)
.attr("y2", y)
.attr("stroke", "#222")
.attr("stroke-width", 2);
});

c.gates.forEach((g) => {
const x = 100 + g.t * spacingX;

if (g.type === "h" || g.type === "x") {
const y = 60 + g.qubit * spacingY;
svg
.append("rect")
.attr("x", x - 20)
.attr("y", y - 20)
.attr("width", 40)
.attr("height", 40)
.attr("fill", "white")
.attr("stroke", "black");

svg
.append("text")
.attr("x", x)
.attr("y", y + 5)
.attr("text-anchor", "middle")
.attr("font-weight", "bold")
.text(g.type.toUpperCase());
}

if (g.type === "cnot") {
const yC = 60 + g.control * spacingY;
const yT = 60 + g.target * spacingY;

svg.append("circle").attr("cx", x).attr("cy", yC).attr("r", 7).attr("fill", "black");
svg
.append("line")
.attr("x1", x)
.attr("x2", x)
.attr("y1", yC)
.attr("y2", yT)
.attr("stroke", "black");

svg
.append("circle")
.attr("cx", x)
.attr("cy", yT)
.attr("r", 12)
.attr("stroke", "black")
.attr("fill", "white");

svg
.append("line")
.attr("x1", x - 8)
.attr("x2", x + 8)
.attr("y1", yT)
.attr("y2", yT)
.attr("stroke", "black");

svg
.append("line")
.attr("x1", x)
.attr("x2", x)
.attr("y1", yT - 8)
.attr("y2", yT + 8)
.attr("stroke", "black");
}
});
}

useEffect(() => {
drawCircuit(activeCircuit);
}, [activeCircuit]);
}, [activeCircuit, svgWidth]);

return (
<div style={{ width: "100%", padding: "20px" }}>
Expand Down
2 changes: 1 addition & 1 deletion components/Visualization/svgs/No_Viz_SVG.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import React, { useContext } from 'react';
import Box from '@mui/material/Box';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutlined';
import { Typography,Card } from '@mui/material';
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
Expand Down
57 changes: 30 additions & 27 deletions components/Visualization/svgs/StandardCircuitSvgReact.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,33 @@ const CIRCUIT_MARGIN = { top: 80, right: 30, bottom: 40, left: 70 };
const GATE_WIDTH = 44;
const GATE_HEIGHT = 26;

const GATE_PALETTE = {
oracle: { label: "Oracle", fill: getColorByKey("Purple") || "#AA4499" },
block: { label: "Block", fill: getColorByKey("Sand") || "#DDCC77" },
rz: { label: "RZ", fill: getColorByKey("Teal") || "#44AA99" },
ry: { label: "RY", fill: getColorByKey("Cyan") || "#88CCEE" },
rx: { label: "RX", fill: getColorByKey("Rose") || "#CC6677" },
u3: { label: "U3", fill: getColorByKey("Olive") || "#999933" },
u2: { label: "U2", fill: getColorByKey("Olive") || "#999933" },
u1: { label: "U1", fill: getColorByKey("Olive") || "#999933" },
};
const GATE_TITLE_MAP = {
h: "Hadamard",
x: "Pauli-X",
y: "Pauli-Y",
z: "Pauli-Z",
cx: "CNOT",
m: "Measurement",
oracle: "Oracle",
block: "Block",
rz: "RZ",
ry: "RY",
rx: "RX",
u1: "U1",
u2: "U2",
u3: "U3",
};

// Renders a quantum circuit layout using D3. Supports single-qubit gates (h, x),
// controlled-not (cx), measurements (m), and additional labeled gates (oracle, block,
// rz, ry, u3, etc). If the backend sends an payload string, we parse it;
Expand All @@ -26,32 +53,8 @@ export default function StandardCircuitSvgReact({

const parsedData = parseCircuitData(problemData);

const gatePalette = {
oracle: { label: "Oracle", fill: getColorByKey("Purple") || "#AA4499" },
block: { label: "Block", fill: getColorByKey("Sand") || "#DDCC77" },
rz: { label: "RZ", fill: getColorByKey("Teal") || "#44AA99" },
ry: { label: "RY", fill: getColorByKey("Cyan") || "#88CCEE" },
rx: { label: "RX", fill: getColorByKey("Rose") || "#CC6677" },
u3: { label: "U3", fill: getColorByKey("Olive") || "#999933" },
u2: { label: "U2", fill: getColorByKey("Olive") || "#999933" },
u1: { label: "U1", fill: getColorByKey("Olive") || "#999933" },
};
const gateTitleMap = {
h: "Hadamard",
x: "Pauli-X",
y: "Pauli-Y",
z: "Pauli-Z",
cx: "CNOT",
m: "Measurement",
oracle: "Oracle",
block: "Block",
rz: "RZ",
ry: "RY",
rx: "RX",
u1: "U1",
u2: "U2",
u3: "U3",
};
const gatePalette = GATE_PALETTE;
const gateTitleMap = GATE_TITLE_MAP;

useEffect(() => {
if (!parsedData) return;
Expand Down Expand Up @@ -507,7 +510,7 @@ export default function StandardCircuitSvgReact({
offsetX += 18 + label.length * 7;
});
}
}, [parsedData, useSolutionCircuit]);
}, [parsedData, useSolutionCircuit, gatePalette, gateTitleMap, margin.bottom, margin.left, margin.right, margin.top]);

const oracle = parsedData?.metadata?.oracleType;
const solution = parsedData?.metadata?.solution;
Expand Down
6 changes: 4 additions & 2 deletions components/Visualization/svgs/StandardGraphSvgReact.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import * as d3 from "d3";
import { useEffect, useRef, useState } from "react";
import { getColorByKey } from '../constants/VisColorsArray';

const GRAPH_MARGIN = { top: 200, right: 30, bottom: 30, left: 200 };

function ForceGraph({ w, h, charge, problemData, gadgetMap }) {
const margin = { top: 200, right: 30, bottom: 30, left: 200 },
const margin = GRAPH_MARGIN,
width = w - margin.left - margin.right,
height = h - margin.top - margin.bottom;

Expand Down Expand Up @@ -255,7 +257,7 @@ function ForceGraph({ w, h, charge, problemData, gadgetMap }) {
.text(d => d.name);
}

}, [problemData, charge, gadgetMap]);
}, [problemData, charge, gadgetMap, height, width, margin.left, margin.top]);

return (
<svg
Expand Down
3 changes: 2 additions & 1 deletion components/eventHandlers/handleParameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ export const useHandleParameters = () => {
// Remove parameters from the URL
router.replace(window.location.pathname, undefined, { shallow: true });
document.title = 'Redux';
}, []);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // Intentionally mount-only: URL params should be read and cleaned exactly once on load.
};
4 changes: 2 additions & 2 deletions components/hooks/ProblemProvider/Problem.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function useProblemInfo(url, problemName) {
(async () => {
setProblemInfo(problemName ? (await requestInfo(url, problemName)) ?? {} : {});
})();
}, [problemName]);
}, [problemName, url]);

return problemInfo; // There should be no reason to set the problem information
}
Expand All @@ -35,7 +35,7 @@ function useProblemInfoMap(url) {
const problems = (await requestProblems(url)) ?? [];
setProblemInfoMap(await requestProblemInfoMap(url, problems));
})();
}, []);
}, [url]);

async function requestProblemInfoMap(url, problems) {
let map = new Map();
Expand Down
Loading
Loading