# sdpfun

sdpfun can be used to apply essentially arbitrary unsupported operators on sdpvar objects

## Syntax

```
y = sdpfun(arg1,arg2,...,argn,'function')
```

## Examples

General nonlinear functions are supported through the [callback nonlinear operator framework]. Most functions (exponentials, logarithms, trigonometrics, etc.) are available from start, but the user can use sdpfun as a last black-box resort to define other (elementwise) functions, without going through the hassle of creating new files (although that is the preferred approach).

The following example shows how we can use a nonlinear solver to find a local optimizer to a small trigonometric problem **sin** is already overloaded, but we use it here for illustrative purposes).

```
sdpvar x
y = sdpfun(10*x,'sin')
optimize([-pi <= x <= pi],y+abs(x))
```

Nonlinear operators defined using the sdpfun command can be used in the global solver BMIBNB. Performance is poor though, since the bounding procedures have to be done ad-hoc in every node during the branching process (using sampling)

```
sdpvar x
y = sdpfun(10*x,'sin')
optimize([-pi <= x <= pi],y+abs(x),sdpsettings('solver','bmibnb'))
```

By using function handles, we can redefine functions (they will still work correctly on doubles)

```
sdpvar x
sin = @(x) sdpfun(x,'sin');
optimize([-pi <= x <= pi],sin(10*x)+abs(sin(x))+x,sdpsettings('solver','bmibnb'));
value(x)
t = (-pi:0.01:pi);
plot(t,sin(10*t)+abs(sin(t))+t)
hold on;
plot(value(x),value(sin(10*x)+abs(sin(x))+x),'r+')
```

Anonymous functions can be also in the function definition.

```
clear sin % To avoid aby problems from code above
sdpvar x
strange = @(x) sdpfun(x,'@(x) sin(10*x)+abs(sin(x))+x');
optimize([-pi <= x <= pi],strange(x),sdpsettings('solver','bmibnb'));
value(x)
```

Notice that there is an important difference between this model, and the model where only **sin** was defined. When only **sin** is defined, the solver will work with 3 variables to describe the objective; callback variables to evaluate **sin(x)** and **sin(10*x)**, and a third variable to model absolute values. When the anonymous functions is used, there will only be one callback variable in the objective. In other words, the **sin** and absolute value operator will never be applied on a symbolic sdpvar variable, but only on numerical values of **x** along the solution process.

The command can be useful for redefining how some functions are implemented. As an example, if **abs** is used in a nonconvex way in YALMIP, it is modeled using a mixed-integer representation. If you instead want to solve the nonconvex problem by simply treating **abs** as a general (non-smooth) nonlinear function, simply redefine it as a anonymous function.

The following problem will be solved as a mixed-integer linear program since YALMIP detects that the absolute value is used in a nonconvex way and thus implements a mixed integer description.

```
sdpvar y
constraints = [-5 <= y <= 5, abs(y-2)>=1];
optimize(constraints,y)
```

The following alternative will be solved as a general nonlinear program since YALMIPs implementation of the abs operator will be avoided.

```
sdpvar y
abs = @(x) sdpfun(x,'@(x) abs(x)');
constraints = [-5 <= y <= 5, abs(y-2)>=1];
optimize(constraints,y)
clear abs
```

## Comments

Note that these functions should be used with care in the global solver BMIBNB. The reason is that the global solver needs bounding functions etc for performance (and correctness). Since these are missing (they are approximated by sampling the function along its domain), the global solver is not guaranteed to work. If you really need a new nonlinear operator to be strictly supported in BMIBNB (i.e. with an optimized bounding strategy), make a feature request.