classdef basic_unconstrained
    %{
        A trivial example with no constraints and no dependencies between
        the upper and lower-level programs is used to diagnose solvers.
        minimise    (x1 - 1)^2 + (x2 + 2)^2 + (x3 - 3)^2 + (x4 - 4)^2 
        subject to  y = argmin((y1 - 1)^2 + (y2 + 2)^2 + (y3 - 3)^2 + (y4 - 4)^2 )
    %}
    properties(Constant)
        name = 'basic_unconstrained';
        category = 'miscellaneous';
        subcategory = '';
        datasets = {};
        x0 = [1.0,  -2.0,  3.0, -4.0];
        y0 = [1.0,  -2.0,  3.0, -4.0];
    end


    methods(Static)

        % Upper-level objective function
        function val = F(x, ~, ~)
            val = (x(1)-1)^2 + (x(2)+2)^2 + (x(3)-3)^2 + (x(4)+4)^2;
        end
        
        % Upper-level inequality constraints
        function val = G(~, ~, ~)
            val = [];
        end
        
        % Upper-level equality constraints
        function val = H(~, ~, ~)
            val = [];
        end
        
        % Lower-level objective function
        function val = f(~, y, ~)
            val = (y(1)-1)^2 + (y(2)+2)^2 + (y(3)-3)^2 + (y(4)+4)^2 + 5.0;
        end
        
        % Lower-level inequality constraints
        function val = g(~, ~, ~)
            val = [];
        end
        
        % Lower-level equality constraints
        function val = h(~, ~, ~)
            val = [];
        end

        % If the bilevel program is parameterized by data, this function should
        %  provide code to read data file and return an appropriate structure.
        function val = read_data(~)
            val = [];
        end

        % Key are the function/variable names
        % Values are their dimention
        function n = dimentions(key, ~)
            n = dictionary( ...
                'x', 4, ...
                'y', 4, ...
                'F', 1, ...
                'G', 0, ...
                'H', 0, ...
                'f', 1, ...
                'g', 0, ...
                'h', 0 ...
            );
            if isKey(n,key)
                n = n(key);
            end
        end
    end
end