Skip to main content
Glama

solve_highs_problem

Solve linear and mixed-integer programming problems using the HiGHs solver. Input problem definitions with variables, objectives, and constraints to obtain optimal solutions.

Instructions

Solve a HiGHs linear/mixed-integer programming problem.

This tool takes a HiGHs optimization problem defined with variables, objective,
and constraints, and returns a solution if one exists.

HiGHs is a high-performance linear programming solver that supports:
- Linear programming (LP)
- Mixed-integer programming (MIP)
- Both dense and sparse constraint matrices
- Various solver algorithms (simplex, interior point, etc.)

Example problem structure:
{
    "problem": {
        "sense": "minimize",
        "objective": {
            "linear": [1.0, 2.0, 3.0]
        },
        "variables": [
            {"name": "x1", "lb": 0, "ub": 10, "type": "cont"},
            {"name": "x2", "lb": 0, "ub": null, "type": "cont"},
            {"name": "x3", "lb": 0, "ub": 1, "type": "bin"}
        ],
        "constraints": {
            "dense": [
                [1, 1, 0],
                [0, 1, 1]
            ],
            "sense": ["<=", ">="],
            "rhs": [5, 3]
        }
    },
    "options": {
        "time_limit": 60.0,
        "output_flag": false
    }
}

Args:
    problem: The HiGHs problem definition with variables, objective, and constraints

Returns:
    A list of TextContent containing the solution or an error message

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
problemYes

Implementation Reference

  • The FastMCP tool handler function for 'solve_highs_problem', which receives a HiGHSProblem and delegates to the highs solver, returning JSON-formatted results.
    @app.tool("solve_highs_problem")
    async def solve_highs_problem_tool(problem: HiGHSProblem) -> list[TextContent]:
        """Solve a HiGHs linear/mixed-integer programming problem.
    
        This tool takes a HiGHs optimization problem defined with variables, objective,
        and constraints, and returns a solution if one exists.
    
        HiGHs is a high-performance linear programming solver that supports:
        - Linear programming (LP)
        - Mixed-integer programming (MIP)
        - Both dense and sparse constraint matrices
        - Various solver algorithms (simplex, interior point, etc.)
    
        Example problem structure:
        {
            "problem": {
                "sense": "minimize",
                "objective": {
                    "linear": [1.0, 2.0, 3.0]
                },
                "variables": [
                    {"name": "x1", "lb": 0, "ub": 10, "type": "cont"},
                    {"name": "x2", "lb": 0, "ub": null, "type": "cont"},
                    {"name": "x3", "lb": 0, "ub": 1, "type": "bin"}
                ],
                "constraints": {
                    "dense": [
                        [1, 1, 0],
                        [0, 1, 1]
                    ],
                    "sense": ["<=", ">="],
                    "rhs": [5, 3]
                }
            },
            "options": {
                "time_limit": 60.0,
                "output_flag": false
            }
        }
    
        Args:
            problem: The HiGHs problem definition with variables, objective, and constraints
    
        Returns:
            A list of TextContent containing the solution or an error message
        """
        result = solve_highs_problem(problem)
    
        match result:
            case Success(solution):
                return [
                    TextContent(
                        type="text",
                        text=json.dumps(
                            {
                                "status": solution.status.value,
                                "objective_value": solution.objective_value,
                                "solution": solution.solution,
                                "dual_solution": solution.dual_solution,
                                "variable_duals": solution.variable_duals,
                            }
                        ),
                    )
                ]
            case Failure(error):
                return [TextContent(type="text", text=f"Error solving problem: {error}")]
            case _:
                return [
                    TextContent(
                        type="text",
                        text="Unexpected error in solve_highs_problem_tool",
                    )
                ]
  • Pydantic schema/model defining the input structure for the solve_highs_problem tool: HiGHSProblem.
    class HiGHSProblem(BaseModel):
        """Complete HiGHS optimization problem."""
    
        problem: HiGHSProblemSpec = Field(..., description="Problem specification")
        options: HiGHSOptions | None = Field(None, description="Solver options")
  • Registration of the 'solve_highs_problem' tool using FastMCP's @app.tool decorator.
    @app.tool("solve_highs_problem")
  • Core helper function 'solve_problem' (aliased as solve_highs_problem) that implements the actual HiGHS solver logic using the highspy library.
    def solve_problem(problem: HiGHSProblem) -> Result[HiGHSOutput, str]:
        """Solve a HiGHs optimization problem."""
        try:
            # Create HiGHs instance
            h = highspy.Highs()
    
            # Always disable output for MCP server compatibility
            h.setOptionValue("output_flag", False)
            h.setOptionValue("log_to_console", False)
    
            # Apply options
            options_result = _apply_options(h, problem.options)
            if isinstance(options_result, Failure):
                return options_result
    
            problem_spec = problem.problem
            num_vars = len(problem_spec.variables)
            num_constraints = len(problem_spec.constraints.sense)
    
            # Set up objective
            obj_coeffs = np.array(problem_spec.objective.linear, dtype=float)
            if len(obj_coeffs) != num_vars:
                return Failure(
                    f"Objective coefficients length ({len(obj_coeffs)}) doesn't match number of variables ({num_vars})"
                )
    
            # Set up variable bounds
            var_lower = np.zeros(num_vars, dtype=float)
            var_upper = np.full(num_vars, highspy.kHighsInf, dtype=float)
    
            for i, var_spec in enumerate(problem_spec.variables):
                lb, ub = _get_variable_bounds(var_spec, i)
                var_lower[i] = lb
                var_upper[i] = ub
    
            # Build constraint matrix
            matrix_result = _build_constraint_matrix(problem_spec)
            if isinstance(matrix_result, Failure):
                return matrix_result
    
            rows, cols, values = matrix_result.unwrap()
    
            # Set up constraint bounds
            constraint_lower = np.zeros(num_constraints, dtype=float)
            constraint_upper = np.zeros(num_constraints, dtype=float)
    
            for i, (sense, rhs) in enumerate(
                zip(
                    problem_spec.constraints.sense,
                    problem_spec.constraints.rhs,
                    strict=False,
                )
            ):
                lb, ub = _convert_constraint_sense(sense, rhs)
                constraint_lower[i] = lb
                constraint_upper[i] = ub
    
            # Add variables
            h.addCols(
                num_vars,
                obj_coeffs,
                var_lower,
                var_upper,
                0,
                np.array([]),
                np.array([]),
                np.array([]),
            )
    
            # Set variable integrality constraints
            integrality = np.zeros(num_vars, dtype=int)  # 0 = continuous
            for i, var_spec in enumerate(problem_spec.variables):
                if var_spec.type == HiGHSVariableType.BINARY:
                    integrality[i] = 1  # 1 = integer (binary is integer with bounds 0-1)
                elif var_spec.type == HiGHSVariableType.INTEGER:
                    integrality[i] = 1  # 1 = integer
                # else: continuous (already 0)
    
            # Apply integrality constraints if any variables are integer/binary
            if np.any(integrality > 0):
                h.changeColsIntegrality(num_vars, np.arange(num_vars), integrality)
    
            # Add constraints using sparse format
            if len(rows) > 0:
                # Convert to row-wise sparse format for HiGHs
                # Group by rows and create start array
                unique_rows = np.unique(rows)
                start_array = np.zeros(num_constraints + 1, dtype=int)
    
                for row in unique_rows:
                    start_array[row] = np.sum(rows < row)
    
                start_array[-1] = len(rows)  # Final start
    
                h.addRows(
                    num_constraints,
                    constraint_lower,
                    constraint_upper,
                    len(values),
                    start_array,
                    cols,
                    values,
                )
            else:
                # No constraints case
                h.addRows(
                    num_constraints,
                    constraint_lower,
                    constraint_upper,
                    0,
                    np.array([0]),
                    np.array([]),
                    np.array([]),
                )
    
            # Set objective sense
            if problem_spec.sense == HiGHSSense.MAXIMIZE:
                h.changeObjectiveSense(highspy.ObjSense.kMaximize)
            else:
                h.changeObjectiveSense(highspy.ObjSense.kMinimize)
    
            # Solve the problem
            h.run()
    
            # Get results
            model_status = h.getModelStatus()
            solution = h.getSolution()
            info = h.getInfo()
    
            # Convert status
            status = _convert_status(model_status)
    
            # Extract solution values
            solution_values = solution.col_value if hasattr(solution, "col_value") else []
            dual_values = solution.row_dual if hasattr(solution, "row_dual") else []
            reduced_costs = solution.col_dual if hasattr(solution, "col_dual") else []
    
            # Get objective value
            objective_value = (
                info.objective_function_value
                if hasattr(info, "objective_function_value")
                else 0.0
            )
    
            return Success(
                HiGHSOutput(
                    status=status,
                    objective_value=objective_value,
                    solution=list(solution_values),
                    dual_solution=list(dual_values),
                    variable_duals=list(reduced_costs),
                )
            )
    
        except Exception as e:
            return Failure(f"Error solving HiGHs problem: {e}")
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden and does well by disclosing key behavioral traits: it solves optimization problems, returns a solution or error message, and supports specific HiGHs features (LP/MIP, matrices, algorithms). It mentions the tool 'returns a solution if one exists,' indicating conditional outcomes. However, it doesn't cover performance aspects like computational intensity, memory usage, or error handling details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded: the first two sentences state the core purpose and behavior. Subsequent sections (HiGHs features, example, Args/Returns) are organized for clarity. While comprehensive, some details in the example could be streamlined, but overall it earns its place by providing essential context for a complex tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (optimization solver with one parameter but nested structure), no annotations, and no output schema, the description is largely complete. It covers purpose, input semantics with an example, and return behavior. However, it lacks details on output format (beyond 'list of TextContent') and doesn't address potential solver limitations or edge cases, leaving minor gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate fully. It provides extensive parameter semantics: defines the 'problem' parameter with a detailed example structure, explains components (sense, objective, variables, constraints, options), and clarifies HiGHs-specific elements like variable types and constraint matrices. This adds significant meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Solve a HiGHs linear/mixed-integer programming problem' with specific verbs ('solve') and resources ('HiGHs optimization problem'). It distinguishes from siblings by specifying HiGHs solver capabilities (LP/MIP, dense/sparse matrices, various algorithms), differentiating from other solvers like CVXPY, OR-Tools, and Z3.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context through the example problem structure and HiGHs capabilities, suggesting this tool is for optimization problems solvable by HiGHs. However, it lacks explicit guidance on when to use this versus alternatives like 'simple_highs_solver' or other solver siblings, and doesn't mention prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sdiehl/usolver'

If you have feedback or need assistance with the MCP directory API, please join our Discord server