feat: Major update with validators, skills, dashboard, and docs reorganization

- Add validation framework (config, model, results, study validators)
- Add Claude Code skills (create-study, run-optimization, generate-report,
  troubleshoot, analyze-model)
- Add Atomizer Dashboard (React frontend + FastAPI backend)
- Reorganize docs into structured directories (00-09)
- Add neural surrogate modules and training infrastructure
- Add multi-objective optimization support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-25 19:23:58 -05:00
parent 74a92803b7
commit e3bdb08a22
155 changed files with 52729 additions and 37 deletions

View File

@@ -22,14 +22,18 @@ interface Objective {
interface ParetoPlotProps {
paretoData: ParetoTrial[];
objectives: Objective[];
allTrials?: ParetoTrial[]; // All trials including non-Pareto
}
type NormalizationMode = 'raw' | 'minmax' | 'zscore';
export function ParetoPlot({ paretoData, objectives }: ParetoPlotProps) {
export function ParetoPlot({ paretoData, objectives, allTrials }: ParetoPlotProps) {
const [normMode, setNormMode] = useState<NormalizationMode>('raw');
if (paretoData.length === 0) {
// Use allTrials if provided, otherwise fall back to paretoData
const trialsToShow = allTrials && allTrials.length > 0 ? allTrials : paretoData;
if (trialsToShow.length === 0) {
return (
<div className="bg-dark-700 rounded-lg p-6 border border-dark-600">
<h3 className="text-lg font-semibold mb-4 text-dark-100">Pareto Front</h3>
@@ -40,12 +44,16 @@ export function ParetoPlot({ paretoData, objectives }: ParetoPlotProps) {
);
}
// Extract raw values
const rawData = paretoData.map(trial => ({
// Create set of Pareto front trial numbers for easy lookup
const paretoTrialNumbers = new Set(paretoData.map(t => t.trial_number));
// Extract raw values for ALL trials
const rawData = trialsToShow.map(trial => ({
x: trial.values[0],
y: trial.values[1],
trial_number: trial.trial_number,
feasible: trial.constraint_satisfied !== false
feasible: trial.constraint_satisfied !== false,
isPareto: paretoTrialNumbers.has(trial.trial_number)
}));
// Calculate statistics for normalization
@@ -89,11 +97,12 @@ export function ParetoPlot({ paretoData, objectives }: ParetoPlotProps) {
rawX: d.x,
rawY: d.y,
trial_number: d.trial_number,
feasible: d.feasible
feasible: d.feasible,
isPareto: d.isPareto
}));
// Sort data by x-coordinate for Pareto front line
const sortedData = [...data].sort((a, b) => a.x - b.x);
// Sort ONLY Pareto front data by x-coordinate for line
const paretoOnlyData = data.filter(d => d.isPareto).sort((a, b) => a.x - b.x);
// Get objective labels with normalization indicator
const normSuffix = normMode === 'minmax' ? ' [0-1]' : normMode === 'zscore' ? ' [z-score]' : '';
@@ -219,24 +228,29 @@ export function ParetoPlot({ paretoData, objectives }: ParetoPlotProps) {
</div>
)}
/>
{/* Pareto front line */}
{/* Pareto front line - only connects Pareto front points */}
<Line
type="monotone"
data={sortedData}
data={paretoOnlyData}
dataKey="y"
stroke="#8b5cf6"
strokeWidth={2}
strokeWidth={3}
dot={false}
connectNulls={false}
isAnimationActive={false}
/>
<Scatter name="Pareto Front" data={data}>
{/* All trials as scatter points */}
<Scatter name="All Trials" data={data}>
{data.map((entry, index) => (
<Cell
key={`cell-${index}`}
fill={entry.feasible ? '#10b981' : '#ef4444'}
r={entry.feasible ? 6 : 4}
opacity={entry.feasible ? 1 : 0.6}
fill={
entry.isPareto
? (entry.feasible ? '#10b981' : '#ef4444') // Pareto: green/red
: (entry.feasible ? '#64748b' : '#94a3b8') // Non-Pareto: gray tones
}
r={entry.isPareto ? 7 : 4}
opacity={entry.isPareto ? 1 : 0.4}
/>
))}
</Scatter>