% PROG. 1 - Introduction to LMI solvers and interpreters (YALMIP + Mosek)
%
% Solves the problem:
%   min  x2
%   s.t. x1 + x2 > 0
%        2*x1 - x2 + 2 < 0
%
% Goal: 1) find one feasible (x1,x2), 2) find the minimum x2 that solves it.

%% Decision variables
% YALMIP represents unknowns as "sdpvar" objects, not plain doubles.
x1 = sdpvar(1,1,'full');
x2 = sdpvar(1,1,'full');

%% Objective function
% We want to minimize x2. trace() is only needed for matrix-valued
% objectives; here x2 is scalar, so trace(x2) is just x2.
Objective = trace(x2);
%Objective = 0;   % uncomment to only test feasibility (ignore the objective)

%% Constraints
% YALMIP/LMI solvers work with non-strict inequalities (>=, <=), so strict
% inequalities (>, <) are approximated with a small margin (1e-8).
Constraints = [];

M1 = x1 + x2;
Constraints = [Constraints, M1 >= 1e-8];        % enforces x1 + x2 > 0

M2 = 2*x1 - x2 + 2;
Constraints = [Constraints, M2 <= -1e-8];       % enforces 2*x1 - x2 + 2 < 0

%% Solver options
% Selects Mosek as the underlying solver; verbose=0 silences solver output.
Options = sdpsettings('solver', 'mosek', 'verbose', 0);

%% Solve
Solution = optimize(Constraints, Objective, Options);

%% Diagnostics
% Solution.problem == 0 means YALMIP found a feasible/optimal solution;
% any other value flags an issue (infeasible, solver error, etc.).
disp(Solution.problem)
disp(Solution.info)
disp(yalmiperror(Solution.problem))

%% Extract and report the result
if Solution.problem == 0
    Value_x1 = value(x1)   % feasible x1
    Value_x2 = value(x2)   % minimum x2 that satisfies the constraints
else
    disp('Unfeasible Problem.');
end