Formal Verification Proof Script Outline
1. System Under Verification (SUV) & Proof Goal
2. Assumptions / Initial Axioms
Define environmental or system preconditions that are assumed to be true.
No assumptions added yet (Axioms). Be precise!
3. Proof Step / Lemma Outline
Break down the main proof into manageable sub-goals (Lemmas).
Verification Script Sequence
The sequence of lemmas and proofs will appear here.
No assumptions added yet (Axioms). Be precise!
'; return; } assumptions.forEach((item, index) => { const li = document.createElement('li'); li.className = 'fvps-list-item'; li.innerHTML = ` A${index + 1}. ${item.content} `; li.querySelector('button').addEventListener('click', () => removeAssumption(item.id)); assumptionList.appendChild(li); }); } function addAssumption() { const content = assumptionInput.value.trim(); if (content) { assumptions.push({ id: generateId(), content }); assumptionInput.value = ''; renderAssumptions(); } } function removeAssumption(id) { assumptions = assumptions.filter(item => item.id !== id); renderAssumptions(); } // --- Proof Step Management --- function renderProofSteps() { stepList.innerHTML = ''; if (proofSteps.length === 0) { stepList.innerHTML = 'The sequence of lemmas and proofs will appear here.
'; return; } proofSteps.forEach((step, index) => { const li = document.createElement('li'); li.className = 'fvps-list-item'; li.innerHTML = ` ${index + 1}. ${step.title}${step.command}
(${step.justification})
`;
li.querySelector('button').addEventListener('click', () => removeStep(step.id));
stepList.appendChild(li);
});
}
function addStep() {
const title = lemmaTitleInput.value.trim();
const command = stepCommandInput.value.trim();
const justification = stepJustificationTextarea.value.trim();
if (!title || !command) {
alert("Please enter a Lemma Title and a Tactic Command.");
return;
}
proofSteps.push({ id: generateId(), title, command, justification: justification || 'No justification provided.' });
renderProofSteps();
// Clear form
lemmaTitleInput.value = '';
stepCommandInput.value = '';
stepJustificationTextarea.value = '';
lemmaTitleInput.focus();
}
function removeStep(id) {
proofSteps = proofSteps.filter(step => step.id !== id);
renderProofSteps();
}
// --- PDF Generation (Ensured functionality) ---
function downloadPDF() {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
alert('Error: jsPDF library loaded.'); return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF('portrait', 'pt', 'a4');
const margin = 40;
const pageWidth = doc.internal.pageSize.getWidth();
let currentY = margin;
// --- Helper function to add structured text sections ---
function addTextSection(title, content, startY) {
const estimatedHeight = 15 + (content.split('\n').length * 12) + 10;
if (startY + estimatedHeight > doc.internal.pageSize.getHeight() - margin) {
doc.addPage();
startY = margin;
}
doc.setFontSize(12);
doc.setFont('helvetica', 'bold');
doc.setTextColor(30, 41, 59);
doc.text(title, margin, startY);
doc.setFontSize(10);
doc.setFont('helvetica', 'normal');
doc.setTextColor(71, 85, 105);
const lines = doc.splitTextToSize(content || 'N/A', pageWidth - margin * 2);
doc.text(lines, margin, startY + 15);
return startY + 15 + lines.length * 12 + 10;
}
// --- Header ---
doc.setFontSize(22);
doc.setFont('helvetica', 'bold');
doc.setTextColor(30, 41, 59);
doc.text("Formal Verification Script Outline", pageWidth / 2, currentY, { align: 'center' });
currentY += 15;
doc.setFontSize(14);
doc.text(projectNameInput.value || 'Untitled Verification Project', pageWidth / 2, currentY, { align: 'center' });
currentY += 30;
// --- Section 1: System & Goal ---
currentY = addTextSection("Verification Tool/Language:", languageInput.value, currentY);
currentY = addTextSection("Verification Method:", methodInput.value, currentY);
currentY = addTextSection("Property to be Proven (Goal):", propertyTextarea.value, currentY);
// --- Section 2: Assumptions ---
doc.setFontSize(14);
doc.setFont('helvetica', 'bold');
doc.text("2. Initial Assumptions / Axioms", margin, currentY);
currentY += 15;
if (assumptions.length > 0) {
const assumptionData = assumptions.map((a, index) => [`A${index + 1}.`, a.content]);
doc.autoTable({
startY: currentY,
body: assumptionData,
theme: 'striped',
styles: { fontSize: 10, minCellHeight: 12 },
columnStyles: { 0: { fontStyle: 'bold', cellWidth: 30, fillColor: [241, 245, 249] } },
margin: { left: margin, right: margin }
});
currentY = doc.autoTable.previous.finalY + 15;
}
// --- Section 3: Proof Steps / Lemmas ---
doc.setFontSize(14);
doc.setFont('helvetica', 'bold');
doc.text("3. Proof Script Sequence (Lemmas & Tactics)", margin, currentY);
currentY += 15;
if (proofSteps.length > 0) {
const stepData = proofSteps.map((step, index) => [
index + 1,
step.title,
step.command,
step.justification
]);
doc.autoTable({
startY: currentY,
head: [['#', 'Lemma/Step', 'Tactic/Command', 'Justification/Dependencies']],
body: stepData,
theme: 'grid',
headStyles: { fillColor: [30, 41, 59], textColor: [255, 255, 255] },
styles: { fontSize: 9, minCellHeight: 15, overflow: 'linebreak' },
columnStyles: { 0: { fontStyle: 'bold', cellWidth: 20 }, 2: { fontStyle: 'italic', cellWidth: 100 } },
margin: { left: margin, right: margin }
});
currentY = doc.autoTable.previous.finalY + 20;
} else {
doc.setFontSize(10);
doc.text("No proof steps outlined.", margin, currentY);
currentY += 20;
}
doc.save('formal-verification-script.pdf');
}
// --- Event Listeners and Initial Load ---
addAssumptionBtn.addEventListener('click', addAssumption);
addStepBtn.addEventListener('click', addStep);
assumptionInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
addAssumption();
}
});
stepList.addEventListener('click', (e) => {
if (e.target.classList.contains('fvps-btn-red')) {
removeStep(e.target.dataset.id);
}
});
assumptionList.addEventListener('click', (e) => {
if (e.target.classList.contains('fvps-btn-red')) {
removeAssumption(e.target.dataset.id);
}
});
pdfBtn.addEventListener('click', downloadPDF);
// Sample Data
assumptions.push({ id: generateId(), content: 'The system clock is monotonically increasing.' });
assumptions.push({ id: generateId(), content: 'Memory allocation failures do not occur during standard operation.' });
proofSteps.push({ id: generateId(), title: 'Base Case: Initial State', command: 'apply (state_check init)', justification: 'Verify initial state satisfies the property.' });
proofSteps.push({ id: generateId(), title: 'Lemma 3.1: Queue Size Invariance', command: 'induction t, auto, rewrite queue_size_def', justification: 'Prove size never exceeds max capacity using induction.' });
renderAssumptions();
renderProofSteps();
});
