diff --git a/src/pages/api/optimizeLP.ts b/src/pages/api/optimizeLP.ts new file mode 100644 index 0000000..330ba08 --- /dev/null +++ b/src/pages/api/optimizeLP.ts @@ -0,0 +1,54 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import GLPK from 'glpk.js'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method === 'POST') { + const { objective, constraints } = req.body; + + try { + const glpk = await GLPK(); + const options = { + msglev: glpk.GLP_MSG_ALL, + presol: true, + cb: { + call: (progress: any) => console.log(progress), + each: 1 + } + }; + + const problem = { + name: 'LP', + objective: { + direction: objective.direction === 'max' ? glpk.GLP_MAX : glpk.GLP_MIN, + name: 'obj', + vars: objective.vars + }, + subjectTo: constraints.map((c: any) => ({ + name: c.name, + vars: c.vars, + bnds: { + type: glpk.GLP_UP, + ub: c.bnds.ub, + lb: c.bnds.lb + } + })) + }; + + const result = glpk.solve(problem, options); + + const lpFormat = `\n# Problem Definition\n + name: ${problem.name}\n + # Objective Function\n + ${problem.objective.direction === glpk.GLP_MAX ? 'max' : 'min'} ${problem.objective.vars.map((v: any) => `${v.coef} ${v.name}`).join(' + ')}\n + # Constraints\n + ${problem.subjectTo.map((c: any) => `${c.vars.map((v: any) => `${v.coef} ${v.name}`).join(' + ')} ${c.bnds.ub ? `<= ${c.bnds.ub}` : ''}`).join('\n')}\n`; + + res.status(200).json({ result, lpFormat }); + } catch (error) { + console.error('Error processing optimization:', error); + res.status(500).json({ message: 'Error processing optimization', error: error.message }); + } + } else { + res.status(405).json({ message: 'Only POST method is allowed' }); + } +} \ No newline at end of file diff --git a/src/pages/api/optimizeMIP.ts b/src/pages/api/optimizeMIP.ts new file mode 100644 index 0000000..3ff00b4 --- /dev/null +++ b/src/pages/api/optimizeMIP.ts @@ -0,0 +1,44 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import GLPK from 'glpk.js'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method === 'POST') { + const { objective, constraints, bounds } = req.body; + + if (!objective || !constraints) { + return res.status(400).json({ message: 'Invalid input data. Ensure that "objective" and "constraints" are provided correctly.' }); + } + + try { + const glpk = await GLPK(); + const options = { msglev: glpk.GLP_MSG_ALL, presol: true }; + + const problem = { + name: 'MIP', + objective: { + direction: objective.direction === 'max' ? glpk.GLP_MAX : glpk.GLP_MIN, + name: 'obj', + vars: objective.vars.map(v => ({ name: v.name, coef: v.coef })) + }, + subjectTo: constraints.map(c => ({ + name: c.name, + vars: c.vars.map(v => ({ name: v.name, coef: v.coef })), + bnds: { + type: glpk.GLP_UP, + lb: c.bnds.lb, + ub: c.bnds.ub + } + })), + binaries: objective.vars.map(v => v.name), + generals: objective.vars.map(v => v.name) + }; + + const result = glpk.solve(problem, options); + res.status(200).json({ result }); + } catch (error) { + res.status(500).json({ message: 'Error processing optimization', error: error.message }); + } + } else { + res.status(405).json({ message: 'Only POST method is allowed' }); + } +} diff --git a/src/pages/api/test.ts b/src/pages/api/test.ts new file mode 100644 index 0000000..c6c67e9 --- /dev/null +++ b/src/pages/api/test.ts @@ -0,0 +1,10 @@ + +import type { NextApiRequest, NextApiResponse } from 'next'; + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method === 'POST') { + res.status(200).json({ message: 'API is working!' }); + } else { + res.status(405).json({ message: 'Method not allowed' }); + } +} \ No newline at end of file diff --git a/src/pages/parseLP.ts b/src/pages/parseLP.ts new file mode 100644 index 0000000..604359f --- /dev/null +++ b/src/pages/parseLP.ts @@ -0,0 +1,36 @@ +type VariableLP = { name: string; coef: number }; +type ConstraintLP = { + name: string; + vars: VariableLP[]; + bnds: { ub: number; lb: number }; +}; + +interface ProblemLP { + objective: { + vars: VariableLP[]; + }; + constraints: ConstraintLP[]; +} + +function createProblemLP( + objectiveVars: VariableLP[], + constraints: { name: string; vars: VariableLP[]; ub: number; lb: number }[] +): ProblemLP { + const constraintsFormatted: ConstraintLP[] = constraints.map((constraint) => ({ + name: constraint.name, + vars: constraint.vars, + bnds: { + ub: constraint.ub, + lb: constraint.lb + } + })); + + const problem: ProblemLP = { + objective: { + vars: objectiveVars + }, + constraints: constraintsFormatted + }; + + return problem; +} \ No newline at end of file diff --git a/src/pages/parseMIP.ts b/src/pages/parseMIP.ts new file mode 100644 index 0000000..1fa534b --- /dev/null +++ b/src/pages/parseMIP.ts @@ -0,0 +1,77 @@ +interface VariableMIP { + name: string; + coef: number; +} + +interface Bounds { + type: number; + ub: number; + lb: number; +} + +interface ConstraintMIP { + name: string; + vars: VariableMIP[]; + bnds: Bounds; +} + +interface Options { + mipgap: number; + tmlim: number; + msglev: number; +} + +interface Problem { + name: string; + objective: { + direction: "min" | "max"; + name: string; + vars: VariableMIP[]; + }; + constraints: ConstraintMIP[]; + binaries?: string[]; + generals?: string[]; + options: Options; +} + +function createProblemMIP( + name: string, + direction: "min" | "max", + objectiveName: string, + objectiveVars: VariableMIP[], + constraints: { name: string; vars: VariableMIP[]; bnds_type: number; ub: number; lb: number }[], + binaries: string[], + generals: string[] = [], + mipgap: number, + tmlim: number, + msglev: number +): Problem { + const constraintsFormatted: ConstraintMIP[] = constraints.map((constraint) => ({ + name: constraint.name, + vars: constraint.vars, + bnds: { + type: constraint.bnds_type, + ub: constraint.ub, + lb: constraint.lb + } + })); + + const problem: Problem = { + name: name, + objective: { + direction: direction, + name: objectiveName, + vars: objectiveVars + }, + constraints: constraintsFormatted, + binaries: binaries.length > 0 ? binaries : undefined, + generals: generals.length > 0 ? generals : undefined, + options: { + mipgap: mipgap, + tmlim: tmlim, + msglev: msglev + } + }; + + return problem; +} \ No newline at end of file