5 Design Overview¶
Fusion is a result of many years of experience in conic optimization. It is a dedicated API for users who want to enjoy a simpler experience interfacing with the solver. This applies to users who regularly solve conic problems, and to new users who do not want to be too bothered with the technicalities of a low-level optimizer. Fusion is designed for fast and clean prototyping of conic problems without suffering excessive performance degradation.
Note that Fusion is an object-oriented framework for conic-optimization but it is not a general purpose modeling language. The main design principles of Fusion are:
Expressiveness: we try to make it nice! Despite not being a modeling language, Fusion yields readable, easy to maintain code that closely resembles the mathematical formulation of the problem.
Seamlessly multi-language : Fusion code can be ported across C++, Python, Java, .NET and with only minimal adaptations to the syntax of each language.
What you write is what MOSEK gets: A Fusion model is fed into the solver with (almost) no additional transformations.
Suppose you have a conic quadratic optimization problem like the efficient frontier in portfolio optimization:
where \(\mu, G\) are input data and \(\alpha\) is an input parameter whose value we want to change between many optimizations. Its representation in Fusion is a direct translation of the mathematical model and could look as follows:
auto x = M->variable(n); auto gamma = M->variable(); auto alpha = M->parameter(); M->objective(ObjectiveSense::Maximize, Expr::sub(Expr::dot(mu, x), Expr::mul(alpha, gamma))); M->constraint(Expr::sub(Expr::sum(x), w), Domain::equalsTo(0.0)); M->constraint(Expr::vstack(gamma, Expr::mul(G->transpose(), x)), Domain::inQCone()); M->constraint(x, Domain::greaterThan(0.0));
Seamless multi-language API
Fusion can easily be ported across the five supported languages. All functionalities and naming conventions remain the same in all of them. This has some advantages:
Simplifies code sharing between developers working in different languages.
Improves code reusability.
Simplifies the transition from R&D to production (for instance from fast-prototyping languages used in R&D to more efficient ones used for high performance).
Here is the same code snippet (creation of a variable in the model) in all languages supported by Fusion. Careful code design can generate models with only the necessary syntactic differences between implementations.
auto x= M->variable("x", 3, Domain::greaterThan(0.0)); // C++
x = M.variable('x', 3, Domain.greaterThan(0.0)) # Python
Variable x = M.variable("x", 3, Domain.greaterThan(0.0)) // Java
Variable x = M.Variable("x", 3, Domain.GreaterThan(0.0)) // C#
What You Write is What MOSEK Gets
Fusion is not a modeling language. Instead it clearly defines the formulation the user must adhere to and only provides functionalities required for that formulation. An important upshot is that Fusion will not modify the problem provided by the user, except for introducing auxiliary variables required to fit the problem into the format of the low-level optimizer API. In other words, the problem that is actually solved is as close as possible to what the user writes.
For example, suppose the user defined a conic constraint
Now the low-level API requires that all variables appearing in all conic constraints are different, and so Fusion will have to replace the conic constraint with
Note, however, that to use the optimizer API directly the user would have to apply the same transformation! A similar situation happens when the user defines a number of linear constraints, which have to be arranged into a large linear constraint matrix \(A\), and so on. So, in effect, the Fusion mechanism only automates operations that the user would have to carry out anyway (using pencil and paper, presumably). Otherwise the optimizer model is a direct copy of the Fusion model.
The main benefits of this approach are:
The user knows what problem is actually being solved.
Dual information is readily available for all variables and constraints.
Only the necessary overhead.
Better control over numerical stability.