Skip to content

Commit

Permalink
message while generating
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben-Foxman committed Nov 14, 2024
1 parent 23009fb commit 77e2531
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 66 deletions.
2 changes: 0 additions & 2 deletions frontend-interface/app/api/simulate/route.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { NextResponse } from 'next/server';
import { spawn } from 'child_process';
import path from 'path';
import { PassThrough } from 'stream';

export async function POST(request) {
console.log('API route /api/simulate called');
Expand Down Expand Up @@ -57,7 +56,6 @@ export async function POST(request) {
});

console.log('Quantum simulation completed successfully');
console.log(simulationResult.density_matrix);

return NextResponse.json({
message: 'Simulation completed successfully',
Expand Down
93 changes: 29 additions & 64 deletions frontend-interface/components/DragAndDropGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,24 @@ import {
Droppable,
Draggable,
} from '@hello-pangea/dnd';
import { v4 as uuidv4 } from 'uuid';
import { createClient } from '@supabase/supabase-js';
import Image from 'next/image';
import { useEffect } from 'react';
import { X } from 'lucide-react';
import { v4 as uuidv4 } from 'uuid';

import DensityPlot from './DensityPlot';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseKey);
import LoadingOverlay from './LoadingOverlay';

const initialIcons = [
{ id: 'cnot-control-down', content: '/icons/CNOT.svg', type: 'CNOT', value: 10 }, // Most complex, highest value
{ id: 'cnot-control-up', content: '/icons/CNOT_down.svg', type: 'CNOT', value: 10 }, // Same as other CNOT
{ id: 'hadamard-gate', content: '/icons/H_Gate.svg', type: 'H_Gate', value: 8 }, // Creates superposition
{ id: 'pauli-x-gate', content: '/icons/X_Gate.svg', type: 'X_Gate', value: 4 }, // Bit flip
{ id: 'pauli-y-gate', content: '/icons/Y_Gate.svg', type: 'Y_Gate', value: 5 }, // Combined X and Z
{ id: 'pauli-z-gate', content: '/icons/Z_Gate.svg', type: 'Z_Gate', value: 3 }, // Phase flip
{ id: 'phase-s-gate', content: '/icons/S_Gate.svg', type: 'S_Gate', value: 6 }, // π/2 phase
{ id: 'phase-t-gate', content: '/icons/T_Gate.svg', type: 'T_Gate', value: 7 }, // π/4 phase
{ id: 'cnot-control-down', content: '/icons/CNOT.svg', type: 'CNOT', value: 10 },
{ id: 'cnot-control-up', content: '/icons/CNOT_down.svg', type: 'CNOT', value: 10 },
{ id: 'hadamard-gate', content: '/icons/H_Gate.svg', type: 'H_Gate', value: 8 },
{ id: 'pauli-x-gate', content: '/icons/X_Gate.svg', type: 'X_Gate', value: 4 },
{ id: 'pauli-y-gate', content: '/icons/Y_Gate.svg', type: 'Y_Gate', value: 5 },
{ id: 'pauli-z-gate', content: '/icons/Z_Gate.svg', type: 'Z_Gate', value: 3 },
{ id: 'phase-s-gate', content: '/icons/S_Gate.svg', type: 'S_Gate', value: 6 },
{ id: 'phase-t-gate', content: '/icons/T_Gate.svg', type: 'T_Gate', value: 7 },
];

const GRID_COLUMNS = 10;
const MAX_ROWS = 5;

Expand All @@ -44,6 +40,8 @@ export default function DragAndDropGrid() {
}))
)
);
const [simulationResults, setSimulationResults] = useState(null);
const [isSimulating, setIsSimulating] = useState(false);

const addWire = () => {
if (numRows < MAX_ROWS) {
Expand All @@ -59,19 +57,16 @@ export default function DragAndDropGrid() {
};

const removeWire = (wireIndex) => {
if (numRows > 1) { // Changed from 2 to 1
// Create new grid without the removed wire
if (numRows > 1) {
const newGrid = grid.filter((_, idx) => idx !== wireIndex);

// Remove any CNOT gates that had control or target on the removed wire
const finalGrid = newGrid.map(row =>
row.map(cell => {
if (cell.gate?.type === 'CNOT') {
const [control, target] = cell.gate.wireIndices || [0, 1];
if (control === wireIndex || target === wireIndex) {
return { gate: null, occupiedBy: null };
}
// Adjust wire indices for remaining CNOT gates
const newControl = control > wireIndex ? control - 1 : control;
const newTarget = target > wireIndex ? target - 1 : target;
return {
Expand All @@ -91,19 +86,8 @@ export default function DragAndDropGrid() {
}
};

const getRowValues = (rowIndex) => {
const row = grid[rowIndex];
return row.map((cell) => {
if (cell.gate && cell.gate.value !== null) {
return cell.gate.value;
}
return 0;
});
};

const isCNOTConflict = (destRow, destCol, gateType, currentGateId = null) => {
if (!gateType.startsWith('CNOT')) {
// For single-qubit gates, only check if trying to place on a wire that's part of a CNOT
const cell = grid[destRow][destCol];
return cell.occupiedBy && grid.some(row =>
row[destCol]?.gate?.type === 'CNOT' &&
Expand All @@ -112,12 +96,10 @@ export default function DragAndDropGrid() {
);
}

// For CNOT gates, only check the target wires
const targetRow = (destRow + 1) % numRows;
return grid[destRow][destCol].gate !== null || grid[targetRow][destCol].gate !== null;
};


const onDragEnd = async (result) => {
const { source, destination, draggableId } = result;

Expand All @@ -141,15 +123,6 @@ export default function DragAndDropGrid() {
newGrid[sourceRow][sourceCol] = { gate: null, occupiedBy: null };
setGrid(newGrid);
}

try {
await supabase
.from('icon_positions')
.delete()
.eq('id', draggableId);
} catch (error) {
console.error('Error deleting data:', error);
}
}
return;
}
Expand All @@ -170,9 +143,7 @@ export default function DragAndDropGrid() {
}

if (cellData.gate.type.startsWith('CNOT')) {
const controlQubit = sourceRow;
const targetQubit = (controlQubit + 1) % numRows;

const targetRow = (destRow + 1) % numRows;
let newGrid = grid.map((row, rowIndex) => {
const newRow = [...row];
if (newRow[sourceCol].occupiedBy === cellData.gate.id) {
Expand All @@ -181,19 +152,17 @@ export default function DragAndDropGrid() {
return newRow;
});

// Place CNOT with updated control and target qubits
newGrid = newGrid.map((row, rowIndex) => {
const newRow = [...row];
if (rowIndex === destRow) {
const targetRow = (destRow + 1) % numRows;
newRow[destCol] = {
gate: {
...cellData.gate,
wireIndices: [destRow, targetRow]
},
occupiedBy: cellData.gate.id,
};
} else if (rowIndex === (destRow + 1) % numRows) {
} else if (rowIndex === targetRow) {
newRow[destCol] = {
gate: null,
occupiedBy: cellData.gate.id,
Expand All @@ -213,16 +182,6 @@ export default function DragAndDropGrid() {

setGrid(newGrid);
}

try {
await supabase
.from('icon_positions')
.update({ position_x: destCol, position_y: destRow })
.eq('id', draggableId);
} catch (error) {
console.error('Error updating data:', error);
}

return;
}

Expand Down Expand Up @@ -278,10 +237,8 @@ export default function DragAndDropGrid() {
const cell = grid[row][col];
if (cell.gate) {
if (cell.gate.type === 'CNOT' && cell.gate.wireIndices?.[0] === row) {
// Only add CNOT gate once, when we're at the control qubit
currentLayer.push(['CX', ...cell.gate.wireIndices]);
} else if (!cell.gate.type.startsWith('CNOT')) {
// Single qubit gates
currentLayer.push([cell.gate.type.replace('_Gate', ''), row]);
}
}
Expand All @@ -294,6 +251,7 @@ export default function DragAndDropGrid() {
};

const handleSimulate = async () => {
setIsSimulating(true);
try {
const ir = convertGridToIR();
const response = await fetch('/api/simulate', {
Expand All @@ -307,11 +265,12 @@ export default function DragAndDropGrid() {
}
} catch (error) {
console.error('Error:', error);
alert('Error generating circuit: ' + error.message);
} finally {
setIsSimulating(false);
}
};

const [simulationResults, setSimulationResults] = useState(null);

return (
<div style={{ backgroundColor: '#fff', minHeight: '100vh', color: 'black' }}>
{/* Title Section */}
Expand All @@ -329,14 +288,19 @@ export default function DragAndDropGrid() {
margin: 0,
letterSpacing: '0.5px'
}}>
NISQ Quantum Simulator
Design and simulate quantum circuits <br />
in a noisy intermediate-scale quantum environment.
</h1>
<p style={{
fontSize: '1.1rem',
color: '#6c757d',
marginTop: '10px'
marginTop: '15px',
lineHeight: '1.6'
}}>
Design and simulate quantum circuits in a noisy intermediate-scale quantum environment.
Perfect for all your VQE needs, <br />
we support a wide range of gates (and depolarizing noise!)<br />
Perfect for the "simulations" section of your paper! <br />
(Which no one will read)
</p>
</div>

Expand Down Expand Up @@ -560,6 +524,7 @@ export default function DragAndDropGrid() {
</button>
</div>
<DensityPlot plotImageData={simulationResults?.plotImage} />
<LoadingOverlay isLoading={isSimulating} />
</DragDropContext>
</div>
);
Expand Down
71 changes: 71 additions & 0 deletions frontend-interface/components/LoadingOverlay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useState, useEffect } from 'react';

const loadingMessages = [
"Collapsing those wavefunctions...",
"Entangling qubits...",
"Applying quantum gates...",
"Computing density matrices...",
"Fighting decoherence...",
"Measuring superpositions...",
"Calculating phase shifts...",
"Optimizing your VQE...",
"Adding depolarizing noise...",
"Generating arXiv citations..."
];

const LoadingOverlay = ({ isLoading }) => {
const [messageIndex, setMessageIndex] = useState(0);

useEffect(() => {
if (!isLoading) return;

const interval = setInterval(() => {
setMessageIndex((prev) => (prev + 1) % loadingMessages.length);
}, 2000);

return () => clearInterval(interval);
}, [isLoading]);

if (!isLoading) return null;

return (
<div
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(255, 255, 255, 0.9)',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
zIndex: 1000
}}
>
<div className="animate-pulse text-3xl font-bold mb-4 text-gray-800">
Generating your circuit...
</div>

{/* Quantum Gate Loading Animation */}
<div className="relative w-24 h-24">
<div className="absolute w-full h-full border-8 border-gray-300 rounded-full" />
<div className="absolute w-full h-full border-8 border-blue-500 rounded-full
animate-spin [border-top-color:transparent] [border-left-color:transparent]" />
<div className="absolute w-full h-full border-8 border-green-500 rounded-full opacity-40
animate-spin [animation-duration:3s] [border-bottom-color:transparent] [border-right-color:transparent]" />
<div className="absolute w-full h-full flex items-center justify-center">
<div className="w-4 h-4 bg-blue-500 rounded-full animate-pulse" />
</div>
</div>

{/* Loading Messages */}
<div className="mt-6 text-gray-600 text-lg animate-pulse">
{loadingMessages[messageIndex]}
</div>
</div>
);
};

export default LoadingOverlay;

0 comments on commit 77e2531

Please sign in to comment.