Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/FabianeloV/Metodo-simplex/llms.txt

Use this file to discover all available pages before exploring further.

The frontend is a React 18 single-page application written in TypeScript and bundled by Vite. It applies the atomic design methodology throughout src/components/, grouping reusable UI primitives into atoms, composing them into molecules and organisms, wrapping them in layout templates, and finally assembling full solver experiences as page components. A dedicated service layer handles all HTTP communication with the FastAPI backend, custom hooks encapsulate form state and async dispatch, and shared TypeScript interfaces in src/types/ keep the request and response shapes in sync with Pydantic schemas on the backend.

Entry point

src/main.tsx mounts the React tree into #root inside React’s StrictMode:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./styles/globals.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
);
App.tsx implements a lightweight client-side router using a single screen state value. The last-visited solver method is persisted to localStorage under the key simplex-app:last-method so the user lands back on their preferred tool after a page refresh.
type Screen = Method | "home";

function App() {
  const [screen, setScreen] = useState<Screen>("home");
  const [lastMethod, setLastMethod] = useState<Method>(readLastMethod);

  if (screen === "home")      return <HomePage      lastMethod={lastMethod} onSelect={handleSelect} />;
  if (screen === "binary")    return <BinaryPage    onHome={goHome} />;
  if (screen === "integer")   return <IntegerPage   onHome={goHome} />;
  if (screen === "bisection") return <BisectionPage onHome={goHome} />;
  if (screen === "multivar")  return <MultivarPage  onHome={goHome} />;
  if (screen === "kkt")       return <KKTPage       onHome={goHome} />;
  return <SolverPage onHome={goHome} />;
}

Atomic design layers

The component hierarchy moves from simple, stateless primitives up to full page experiences, with each layer depending only on layers below it.

Atoms

Atoms are the smallest reusable UI elements. They have no knowledge of domain data — they accept only style and callback props.
AtomDescription
ButtonStyled action button with variant and disabled props
InputNumeric and text input with label support
SelectDropdown for goal (max/min) and inequality selectors
BadgeStatus chip for solver result states (optimal, infeasible, unbounded)
LabelAccessible form label wrapper
SpinnerLoading indicator shown during API calls

Molecules

Molecules combine two or more atoms into a small, focused UI unit.
MoleculeDescription
TableauTableRenders the final and per-iteration simplex tableaux from tableau_rows
GraphicalPlotPlotly.js wrapper for 2-D feasible region plots
FunctionPlotPlotly.js wrapper for single-variable function plots (bisection, Newton-Raphson)
Plot3DPlotly.js wrapper for 3-D surface and volume plots (gradient, KKT, graphical multivar)
BBTreeGraphPlotly.js wrapper that visualizes the Branch & Bound exploration tree
TabGroupTab-switching control used to navigate between tableau, graphical, and iteration views
SubTabGroupSecondary tab-switching control for nested view sections
ObjectiveRowA single row of objective coefficient inputs
ConstraintRowOne constraint: coefficient inputs, inequality selector, and RHS input
MetricCardKey-value card displaying a single result metric (e.g. objective value)
ErrorBannerDismissable error message strip

Organisms

Organisms are domain-aware sections of the UI. They own local layout and may manage their own sub-state (e.g. dynamic rows).
OrganismDescription
AppHeaderTop navigation bar with method title and home button
ObjectiveFormFull objective function input section (variable count selector + coefficient row)
ConstraintsFormManages a dynamic list of ConstraintRow molecules with add/remove controls
SolutionDisplayRenders the complete simplex solver result: status badge, metrics, tableau, and graphical output
GraphicalSolutionDisplayRenders the 2-D feasible region and optimal point for 2-variable simplex problems
BinarySolutionDisplayRenders the binary B&B result: optimal variables, objective value, and B&B tree
IntegerSolutionDisplayRenders the pure-integer B&B result and exploration tree
BisectionFormInput form for the bisection single-variable optimizer (polynomial coefficients, interval, tolerance)
BisectionSolutionDisplayRenders bisection iteration table and convergence plot
NewtonFormInput form for the Newton-Raphson single-variable optimizer (coefficients, initial point, tolerance)
NewtonSolutionDisplayRenders Newton-Raphson iteration table and function plot
GradientFormInput form for the gradient descent multi-variable optimizer (expression, variables, initial point, step size)
GradientSolutionDisplayRenders gradient descent iteration table and 3-D surface plot
GraphicalMultivarFormInput form for the graphical multi-variable method (expression, variables, bounds)
GraphicalMultivarSolutionDisplayRenders critical points, 3-D surface, and volume plot for multi-variable graphical output
KKTObjectiveFormInput form for the KKT objective function and variable list
KKTConstraintsFormManages a dynamic list of KKT constraint expressions with inequality selectors
KKTSolutionDisplayRenders KKT cases explored, optimal point, multipliers, and objective value

Templates

Templates are layout skeletons with no domain logic. SolverTemplate defines the two-column or stacked layout that all solver pages share — form on the left, results on the right — without knowing which solver is being displayed.

Pages

Pages are the top-level components mounted by App.tsx. Each page imports a solver-specific hook and passes its state and callbacks into the template.
PageRouteSolver
HomePagehomeMethod selection landing screen
SolverPagesimplexBig-M LP Simplex
BinaryPagebinaryBinary integer programming (B&B)
IntegerPageintegerPure integer programming (B&B)
BisectionPagebisectionSingle-variable bisection method
MultivarPagemultivarMulti-variable gradient + graphical output
KKTPagekktKarush-Kuhn-Tucker conditions

Service layer

Each solver method has a dedicated *Api.ts file in src/services/. All services share the same post<TBody, TResponse> generic helper that reads the base URL from the VITE_API_URL environment variable and converts non-2xx responses into a typed ApiError.
// src/services/simplexApi.ts

import type { SimplexRequest, SimplexResponse } from "../types/simplex";

const BASE_URL = import.meta.env.VITE_API_URL ?? "http://localhost:8000/api/v1";

class ApiError extends Error {
  constructor(
    public readonly status: number,
    message: string,
  ) {
    super(message);
    this.name = "ApiError";
  }
}

async function post<TBody, TResponse>(
  path: string,
  body: TBody,
): Promise<TResponse> {
  const response = await fetch(`${BASE_URL}${path}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });

  if (!response.ok) {
    const detail = await response
      .json()
      .then((d: { detail?: string }) => d.detail ?? response.statusText)
      .catch(() => response.statusText);
    throw new ApiError(response.status, String(detail));
  }

  return response.json() as Promise<TResponse>;
}

export const simplexApi = {
  solve: (payload: SimplexRequest): Promise<SimplexResponse> =>
    post<SimplexRequest, SimplexResponse>("/simplex/solve", payload),
};
Set VITE_API_URL in a .env file at the root of frontend/ to point at a deployed backend. The default falls back to http://localhost:8000/api/v1 for local development.

Hooks layer

Each solver has a matching use*.ts hook in src/hooks/. Hooks encapsulate all async state (result, loading, error) and expose a solve() callback and a reset() helper. They never render anything — they only manage state and call the service layer.
// src/hooks/useSimplex.ts

export function useSimplex() {
  const [state, setState] = useState<UseSolverState>({
    result: null,
    loading: false,
    error: null,
  });

  const solve = useCallback(
    async (
      nVars: VariableCount,
      objCoeffs: number[],
      goal: Goal,
      constraints: Constraint[],
    ) => {
      setState({ result: null, loading: true, error: null });

      try {
        const result = await simplexApi.solve({
          objective: objCoeffs.slice(0, nVars),
          goal,
          constraints: constraints.map((c) => ({
            coefficients: c.coefficients.slice(0, nVars),
            inequality: c.inequality,
            rhs: c.rhs,
          })),
        });
        setState({ result, loading: false, error: null });
      } catch (err) {
        const message =
          err instanceof Error ? err.message : "Ocurrió un error inesperado";
        setState({ result: null, loading: false, error: message });
      }
    },
    [],
  );

  const reset = useCallback(() => {
    setState({ result: null, loading: false, error: null });
  }, []);

  return { ...state, solve, reset };
}
The VariableCount type (2 | 3 | 4 | 5) enforces at the type level that objCoeffs and constraint rows are sliced to a supported size before being sent to the API, preventing accidental over-posting of empty trailing zeros from the form.

TypeScript types

src/types/simplex.ts defines domain aliases and interfaces that mirror the backend Pydantic schemas exactly. These are the single source of truth for both the service layer and all consuming components.
// Domain types
export type Goal          = "max" | "min";
export type Inequality    = "<=" | ">=" | "=";
export type VariableCount = 2 | 3 | 4 | 5;
export type SolveStatus   = "optimal" | "unbounded" | "infeasible";

// API request
export interface SimplexRequest {
  objective: number[];
  goal: Goal;
  constraints: Array<{
    coefficients: number[];
    inequality: Inequality;
    rhs: number;
  }>;
}

// API response
export interface SimplexResponse {
  status: SolveStatus;
  objective_value?: number;
  variables?: Record<string, number>;
  iterations?: number;
  tableau_headers?: string[];
  tableau_rows?: TableauRow[];
  message?: string;
  graphical?: GraphicalData | null;
  iteration_tableaux?: IterationTableau[] | null;
}

Plotly.js integration

The frontend uses plotly.js-dist-min (v3.7.0) and react-plotly.js (v4.0.0) for all chart output. Three distinct chart types are produced depending on the solver:
Chart typeSolverData source
2-D feasible regionSimplex (2-variable)SimplexResponse.graphical — constraint lines, feasible polygon, optimal point
Branch & Bound treeBinary / IntegerBinaryResponse.nodes — node graph with edge labels
3-D surface + volumeGradient / KKTGradientResponseSurfaceData.x/y/z mesh grid
plotly.js-dist-min is the minified pre-built bundle, so no additional Webpack/Rollup configuration for Plotly is needed — Vite can import it directly as an ES module.

Build tooling

The project uses Vite 5 with the @vitejs/plugin-react plugin and TypeScript 5.5.
{
  "scripts": {
    "dev":     "vite",
    "build":   "vite build",
    "preview": "vite preview",
    "lint":    "eslint src --ext ts,tsx --report-unused-disable-directives"
  }
}
ScriptPurpose
npm run devStart Vite HMR dev server at http://localhost:5173
npm run buildBundle the app for production into dist/
npm run previewServe the production bundle locally for testing
npm run lintRun ESLint with TypeScript and React Hooks rules across all .ts and .tsx files

Starting the development server

cd frontend
npm install
cp .env.example .env   # Set VITE_API_URL if needed
npm run dev
Open http://localhost:5173 in the browser. Ensure the backend is running on port 8000 (or update VITE_API_URL in .env) so API calls resolve correctly.

Build docs developers (and LLMs) love