classdef dempe_dutta_3_4
    %{
    Reference:
        Stephan Dempe and Joydeep Dutta.
        Is bilevel programming a special case of a mathematical program with complementarity constraints?
        Mathematical Programming, volume 131, pages 37–48, year 2012.
        Example 3.4
    
    Upper level program:
        minimise x,y    F(x,y)
        subject to      G(x,y) >= 0
                        H(x,y) == 0
                        y solves the lower level program
    
    Lower level program:
        minimise y      f(x,y)
        subject to      g(x,y) >= 0
                        h(x,y) == 0
    %}

    properties(Constant)
        name = 'dempe_dutta_3_4';
        category = 'textbook';
        subcategory = 'dempe_dutta_2012';
        datasets = {};
        x0 = [0.5];
        y0 = [0.5];
    end
    
    methods(Static)
        % Upper-level objective function
        function val = F(x, y, ~)
            % Quadratic
            val = (x(1) - 1)^2 + (y(1) - 1)^2;
        end
        
        % Upper-level inequality constraints (none)
        function vals = G(~, ~, ~)
            vals = [];
        end
        
        % Upper-level equality constraints (none)
        function vals = H(~, ~, ~)
            vals = [];
        end
        
        % Lower-level objective function (linear)
        function val = f(~, y, ~)
            val = -y(1);
        end
        
        % Lower-level inequality constraints (quadratic)
        function val = g(x, y, ~)
            val = [
                -x(1) - y(1) + 1;
                 x(1) - y(1) + 1
            ];
        end
        
        % Lower-level equality constraints (none)
        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', 1, ...
                'y', 1, ...
                'F', 1, ...
                'G', 0, ...
                'H', 0, ...
                'f', 1, ...
                'g', 2, ...
                'h', 0 ...
            );
            if isKey(n,key)
                n = n(key);
            end
        end
    end
end
