Friday, October 2, 2026

What Makes a Solver API Worth Copying?

 Imitation is the sincerest form of flattery.

Recently, a new open-source optimization solver called PRIMAL caught our attention. Not only because it was generated using coding agents, or because it supports an ambitious range of optimization problems — LP, MIP, QP, SOCP, SDP, and more — but also because parts of its API looked remarkably familiar. Replace “MSK_” with “PRIMAL_,” and you can adopt the MOSEK examples quickly.

PRIMAL itself documents that its test suite contains 48 C ports of MOSEK examples and that it performs compatibility validation against the publicly available MOSEK examples. Looking more closely, however, raises a more interesting question than simply whether one API resembles the other:

Why would somebody designing a new optimization solver choose the MOSEK C API as a blueprint?

Many mature solver APIs offer inspiration, including SCIP, HiGHS, and a rich set of open-source and commercial APIs such as CPLEX.

So perhaps this is a good opportunity to look at something we rarely talk about: the design philosophy behind the MOSEK C API. We focus on the low-level C API, which is what you need in the first place to design an optimization solver. Users should be aware of MOSEK’s higher-level constructs across various languages, such as the Fusion API for C++, Python, Java, and .NET.

1. A small and consistent vocabulary

At its core, the MOSEK C API uses a rather small collection of verbs:

Append, put, get, remove

These are then combined systematically with the objects being manipulated:

Var, con, aij, bound, c, solution


This produces functions such as:

MSK_appendvars(...), MSK_appendcons(...), MSK_putcj(...), MSK_putaij(...), MSK_putvarbound(...)

MSK_putconbound(...) 

MSK_getnumvar(...), MSK_getnumcon(...), MSK_getxx(...)

The important part is not any individual function name. It is the regularity of the language. Once you understand the naming convention, you can frequently predict what another function will be called.

This is one characteristic of a good API: users spend less time memorizing names and more time understanding the optimization problem.

2. The API closely follows the mathematics

Consider variable bounds. A variable can be
Free
x >= l
x <= u
l <= x <= u
x = a

Rather than providing a collection of unrelated functions for these cases, the MOSEK API represents them with a bound key and lower and upper bounds. The corresponding C function is:

MSK_putvarbound(task, j, bkx, blx, bux)

Similarly, a constraint has a bound key and lower and upper bounds:

MSK_putconbound(task, i, bkc, blc, buc)

The API therefore mirrors the mathematical representation of the optimization problem. You do not have to think primarily in terms of software objects. You can think in terms of variables, constraints, bounds, and coefficients.

3. Separate the structure from the data

Another characteristic of the MOSEK C API is the separation between creating mathematical objects and specifying their properties. A typical model starts with:

MSK_appendcons(task, numcon)
MSK_appendvars(task, numvar)

We have now created the mathematical structure. Then we populate it:

MSK_putcj(...), MSK_putvarbound(...), MSK_putconbound(...), MSK_putaij(...)

Conceptually, the workflow becomes:

Create task → Create variables and constraints → Populate coefficients, bounds, and objective → Optimize

This may appear almost trivial. That is precisely the point. A good API makes the underlying concepts appear obvious.

4. Scalability: One or ten million coefficients

Designing an optimization API is an interesting challenge. It should be convenient enough to teach with a model containing three variables, while still being suitable for applications containing millions of variables and nonzeros.

For example, the simplest way of changing one element of the constraint matrix is:

MSK_putaij(task, i, j, value);


For larger amounts of data, the same API provides list, row, column and slice operations. The same pattern occurs elsewhere. There are operations for an individual variable bound as well as operations on collections or slices of variable bounds. This gives the API an important property:

The conceptual API used in a small tutorial is also the API used to construct very large optimization models.

Users do not have to abandon the original mental model when their problems become large.

5. An API that survived the evolution from LP to conic optimization

MOSEK has existed for decades, with the first release in 1999. Since then, mathematical optimization software has changed substantially. An API originally dealing with linear and quadratic optimization eventually had to accommodate, among other things:

  • second-order cones,

  • semidefinite optimization,

  • exponential cones,

  • power cones,

  • affine conic constraints,

  • mixed-integer conic optimization.

Yet the fundamental concept of a MOSEK Task has remained. That is important. A software API that works well for today's features is useful. An API whose basic abstractions can accommodate mathematical capabilities that were not anticipated when it was originally designed is something else entirely.

6. Other solvers made different — and perfectly reasonable — choices

This is not to say that there is only one good way to design an optimization API. Consider HiGHS, another optimization solver with a C API. HiGHS exposes a strongly row- and column-oriented interface, with functions such as Highs_addRow and Highs_addCol. MOSEK also provides efficient row- and column-oriented operations, such as MSK_putarow and MSK_putacol, but separates creating mathematical objects (appendvars, appendcons) from populating their coefficients and properties.

MOSEK takes a somewhat different approach. Much of the low-level MOSEK API can be viewed as manipulating a collection of mathematical objects and their properties:

Neither approach is inherently better. HiGHS' terminology maps naturally onto the sparse matrix representation underlying LP and MIP models. MOSEK's abstraction, however, becomes particularly interesting as we move beyond traditional LP and MIP into conic optimization. Variables, constraints, affine expressions, and domains remain mathematical concepts even when the model contains second-order, exponential, power, or semidefinite cones.

This may help explain why the basic vocabulary of the MOSEK API has remained relatively small while the range of optimization problems MOSEK supports has grown substantially.

7. Why not simply copy CPLEX?

CPLEX provides another interesting comparison. Its C API reflects its long history and its row- and column-oriented representation. For example, adding multiple rows involves concepts such as row and nonzero counts, along with sparse-matrix index and value arrays.

That is powerful and efficient. It also exposes more details of how the mathematical matrix is represented.

MOSEK's basic operations (discussed above) provide a somewhat different abstraction. The model looks less like a sparse matrix data structure and more like a collection of mathematical objects whose properties you can query and modify. For a new solver API, that can be an attractive starting point.

8. Wrap-up

This brings us back to PRIMAL. Its developers could have designed an entirely new interface. They could have followed CPLEX's conventions. They could have followed SCIP or HiGHS. Or selected any other solver’s API. So,

What properties of an API make another solver developer want to reproduce its concepts?

Based on the above, our answer would be: 

  • Consistency.

  • A small vocabulary.

  • Predictable naming.

  • A close relationship between API concepts and mathematical concepts.

  • A natural progression from scalar operations to high-performance bulk operations.

  • And abstractions that have remained useful while mathematical optimization has evolved substantially.

After using it for a while, the naming becomes predictable. The abstractions stop attracting attention. You start thinking about the optimization model instead of thinking about the API.

In other words, the API becomes boring. And boring infrastructure is often excellent infrastructure.

To quote MOSEK founder and CEO, Erling D. Andersen: “The mental model and the interface should be as close as possible. At the same time, a low-level API needs to be just generic enough and designed to cover linear, conic, and nonlinear constructs elegantly and extendibly, not being limited to the solution methods such as Simplex or interior point only.”

So when we noticed that a new optimization solver written with an agentic coding assistant had adopted many familiar ideas, our first reaction was naturally curiosity. Our second was perhaps a little bit of pride.

After all, if you are going to take inspiration from a low-level optimization solver API, we are happy ours seems worth studying.


Note that this blog has been written with the support of OpenAI’s ChatGPT 😀


Wednesday, June 24, 2026

MOSEK - LP Energy Benchmarks

Energy optimization is gaining real momentum due to growing environmental consciousness and increasing pressure on energy infrastructure. Several factors contribute, including rising electricity demand from electric vehicles (EVs), expanding data center capacity, and the growing integration of renewable energy sources, which together are increasing system complexity, energy consumption, and strain on power grids. 

Mathematical optimization plays a key role in solving the underlying business problems.

Recent computational studies (https://openenergybenchmark.org/ and https://arxiv.org/abs/2605.04605) mainly compare open-source solvers, and a single or a virtual best-of commercial solvers. In parallel, we are learning from customers and evaluators that MOSEK’s robust interior point solver gives impressive results out of the box on linear energy optimization problems -  even though MOSEK is tuned for other types of problems, in particular finance, forestry, and supply chain. Therefore, we decided to run our own computational study to provide insights into the performance of MOSEK version 11.2, without delving into the intricacies of public benchmarking. 


Key results

  • Default MOSEK is, on average (using shifted geometric mean), about 2.5-4 times faster than the selected default open-source solver.
  • Running MOSEK’s interior-point method in a multi-threaded setting yields speed-ups ranging from 15% (2 threads) to 37% (8 threads) compared to single-threaded performance. 
  • When solving large energy models, memory may be of concern. Reducing from 8 threads to 2 (or 1) threads helps reduce peak memory consumption by 20-40%. 
  • If you are mostly interested in the solution value and don’t require a basic solution, turning basis identification (a.k.a. crossover) off yields, on average, 10% runtime improvement. 


Methodology and computational setup


Methodology: 

  • We use LP instances from https://openenergybenchmark.org/ available on the GitHub page of Open Energy Transition (“OET”).
  • We focus on the 70 medium (M)- sized instances and omit large (L) instances due to the high runtime of open-source solvers. Reporting on too many unsolved large instances is not meaningful. We also decided to limit our runs to 1 hour, which is reasonable for the M instances.
  • We compare MOSEK against itself to provide insights into its workings and to demonstrate the computational trade-offs involved when running with different settings. 
  • We further compare MOSEK version 11.2 with the open-source solver HiGHS in version 1.14. This is to provide readers with an anchor for the publicly available benchmarks
  • For performance comparison, we use the shifted geometric mean (GMST):
  • , where s=10, to follow the standard mean as used by Mittelmann (https://plato.asu.edu/ftp/shgeom.html) and OET (https://openenergybenchmark.org/methodology#ranking-solvers ), and calculate the ratios between the shifted geometric means in column
    GMRST.
  • A solver “wins” (#WINs) when it is not more than 5% slower than the fastest.

Computational set-up: 

  • Machine set-up: We use a single machine of type Supermicro AS-1115HS-TNR-EU – AMD EPYC 9135, 16 cores, 3.65 GHz, 377 GB DDR5-6400 ECC RDIMM memory
  • We use MOSEK default options. No tuning of parameters. 
  • We use a time limit of 1h per instance.
  • We limit each run to 8 threads; any variations for specific experiments are noted below.
  • We executed the solves sequentially, so purely system processes may interfere, which we expect not to accumulate to more than 1% in measurement.


MOSEK versus open-source

For comparison with the results on openenergybenchmarks.com, we include runtime results for HiGHS, an open-source solver. MOSEK is run with the interior-point method, while we tested two runs for HiGHS: the dual simplex method (“DSIM”) and the new multi-threaded, factorization-based interior-point solver HiPO (“HIPO”).

From the table and graphics below, we can see that for small instances, HiGHS performs reasonably well, whereas with increasing complexity, using a commercial solver such as MOSEK quickly makes a significant difference. Observe that 18 instances could not be solved by HiGHS within the time limit, such that the shifted geometric mean is only calculated over 52 of 70 instances. With respect to the shifted geometric mean, HiGHS with HiPO is about 2.5 times (about 4 times with dual simplex) slower than MOSEK. The performance profiles reveal the distance between HiGHS and MOSEK, and further show that HiGHS’ HIPO is usually stronger than HiGHS’ dual simplex on this set of instances. We kept both HiGHS runs mainly because for about 20% of instances, their dual simplex was faster than using HiPO.



Looking at all 68 instances that HiGHS with HiPO could solve within the time limit, the ratio GMRST is about 2.9.


Note that on our fast machine, several runtimes fall into the 5-20-second bucket, and the selected 10-second shift affects the overall ratio. E.g., when setting the shift to s=1 in the shifted geometric mean or similarly when using a less powerful machine (which we initially did), the ratio GMRST between HiGHS and MOSEK increases. When you read about any performance ratios in public benchmarks , it is important to review the instance sets and the calculation logic.


Limited overhead to retrieve basic solutions with MOSEK!


When running primal or dual simplex, you get a basic solution, whereas with an interior-point solver, you need to perform basis identification (a.k.a. crossover) to obtain one. The first question to ask yourself is, do you need a basic solution?

You need it, for example, to perform some types of sensitivity analysis (changes in right-hand side or cost coefficients before basis changes,...), to solve mixed-integer optimization problems, or to obtain a sparse solution. If you are mainly interested in the objective value and need to save time, this step is best skipped, as it is often a computational bottleneck when solving large LPs. Here, we ran an experiment to investigate the impact of the basis identification step on the overall runtime.

Our tests reveal that, on average, only 10% of the time is spent on basis identification, demonstrating its limited impact on overall solving time for MOSEK. In our experience, several solvers tend to spend a lot of time on basis identification (a.k.a. crossover), whereas MOSEK already tends to provide numerically favorable solutions, so retrieving a basic solution does not take long; see the paper by E.D. Andersen “On exploiting problem structure in a basis identification procedure for linear programming” in INFORMS Journal on Computing (https://pubsonline.informs.org/doi/10.1287/mnsc.42.12.1719 ) for more details.

Yet, there are a few outliers in which, for one instance, basis identification took more than 90% of the total runtime. Also, there is one instance where the interior-point method, which ran without basis identification, did not converge and was excluded. So, while it is negligible on average, there are outliers where it may make sense to turn it off.

Threads




Some users have powerful machines and want to run large models one after another, while others may want to solve many problems in parallel. We compare MOSEK running on 1 (“_T1”), 2, 4, and 8 (“_T8”) threads.

The overall runtime improvement on 8 threads is about 37% compared to a single thread. Observe that one instance could not be solved with too few threads; hence, shifted geometric means are calculated over 69 of 70 instances.

In an instance-to-instance comparison, there are a few for which the single-threaded run has been faster (in the graphic, see the blue dots below the red diagonal). Parallelization incurs overhead, and the solution's accuracy may vary, so basis identification may take longer. Using 2 threads may not be worth the overhead, whereas using 4 or 8 threads consistently pays off. For a few other instances, especially from the PyPSA electricity set, using two or more threads was even crucial to solve these in under 30 minutes - look at the maximum runtime 2032 seconds for single-threaded MOSEK versus at most 505 seconds for the multi-threaded ones. 

Memory comparison

Based on the results above and after consultation with energy modeling experts, we created a separate benchmark set containing the realistic PyPSA electricity models from the OET benchmark set to measure memory consumption. Memory measurements in a multi-threaded setup are non-deterministic and should only be used as indicative. From the data, we see that switching from 1 thread (M_DEB1) to 2 threads (M_DEB2) increases the memory by less than 10%, whereas switching to 8 threads (M_DEB) increases it by up to 40%.
Hence, if you are solving large instances and your machine has limited memory, it may be worth running with fewer threads.


Summary


This study provides an indication of MOSEK's strengths for linear optimization problems, in this case from energy applications, and identifies which user controls are worth investigating. We hope this study provides a few anchors to look into and to investigate for your own assessment!

Clearly, results are tied to the instances and computational setup chosen. We always recommend that you check the performance for your own set of instances, and in the environment you are running them - don’t use stronger or much weaker machines for the evaluation; test on machines comparable to your production environment.

Fair benchmarking is challenging - any benchmark requires trade-offs between, for example, representativeness, computational effort, and the practical constraints of available time and resources. We therefore chose to focus on medium-sized instances from the OET benchmark set. These instances are sufficiently challenging to produce meaningful runtime comparisons, yet small enough that open-source solvers can solve a substantial fraction of the test set without excessive timeouts within the imposed time limit. While no benchmark can perfectly capture all real-world scenarios, we believe this selection provides a balanced and informative basis for comparison. 


We encourage you to evaluate MOSEK on the instances that matter to you, with your chosen time limits, be it 10 minutes or 24 hours, and on the machines available to you!


Acknowledgement

We are grateful to the Open Energy Transition for making the Open Energy Benchmark publicly available! You can simply run your own benchmarks on your hardware using their scripts (https://github.com/open-energy-transition/solver-benchmark).








Wednesday, March 25, 2026

Closed during Easter 2026

Support and sales are closed for Easter 2026

from Thursday, April 2nd until Monday, April 6th, inclusive.

Contacting us on April 1st is possible, but only with really good pranks, please 🙂.

Best wishes from the MOSEK team.

Tuesday, February 24, 2026

Guest Speaker Sophie Huiberts: Analyzing the Simplex Method by the Book

On March 17, we are delighted to welcome our guest speaker, Sophie Huiberts, at Mosek office in Copenhagen. Sophie will talk about Simplex method and the gap between theoretical worst case complexity and its observed practical run time. 

If you are curious to learn more, join us at Symbion Park at this publicly open and free event! 

Date and time: 17/3 at 15:00.

Location: Room  M4A ,  Symbion Science Park. (https://www.symbion.dk)
Fruebjergvej 3, 2100 Copenhagen, Denmark

Speaker: Sophie Huiberts, (https://sophie.huiberts.me/)

Title: Analyzing the Simplex Method by the Book
Abstract: The simplex method is an algorithm for linear programming, and this algorithm is much faster than theory is able to explain. In this talk I will describe a new theoretical framework we introduced to address this question. Under this framework, we prove new strong running time guarantees, using mathematical assumptions taken from software user manuals. I will discuss which features of real-world software and LP's we have managed to theoretically capture for this purpose, and what will come next.

Sophie is a CNRS researcher hosted at LIMOS, Clermont Auvergne University in Clermont-Ferrand. And we are happy to welcome her in our office. 


Feel free to join and have a chat with Sophie and the Mosek team !



Wednesday, December 10, 2025

Closed during Christmas

The MOSEK office, sales and support are not available

December 24-28th and 31st, January 1st.

The MOSEK team

Tuesday, September 9, 2025

Hello Autumn!

 While there is still some summer temperatures here in Copenhagen, a certain crispness in the signals that autumn is here!

For MOSEK the arrival of autumn means the arrival of of new persons eligible to use MOSEK for free.

This is because MOSEK, through our academic initiative, grants free licenses for research or educational purposes.  By following the link you can see if you are eligible and request an academic license.

The academic license gives access to the full functionality of MOSEK.

Whether you are a new student or a seasoned academic why not use this opportunity to use MOSEK!

Thursday, July 24, 2025

MOSEK on AWS marketplace

 MOSEK is now available on AWS marketplace as an AMI (Amazon Machine Image). What that means is that you can initiate an instance with MOSEK installed. 

Well actually, you have to install MOSEK on the machine, but there is a script on the AMI that can do that for you!

What is actually pre-installed on the AMI is a MOSEK license. That means you can run MOSEK without having to worry about license files and MAC- addresses. 

Currently we starting off with a limited number of supported instances, but we look to expand on that offering in the near future. 

Since we are still in an experimental mode we are happy to receive any feedback you might have. It can be about which instances you would like us to support or comments on the documentation and user experience, either way we would like to hear from your!

As always you can reach us at support@mosek.com.