classdef bard851
    %{
    Reference 1:
        G. Savard and J. Gauvin,
        The Steepest Descent Direction for the Nonlinear Bilevel Programming Problem
        in Operations Research Letters, Vol. 15, page 265-272, year 1994

    Reference 2:
        Jonathan F. Bard
        Practical Bilevel Optimization: Algorithms And Applications
        Chapter 8, page 336, example 8.5.1
    %}
    properties(Constant)
        name = 'bard851';
        category = 'textbook';
        subcategory = 'bard_1998';
        datasets = {};
        x0 = [1.8888888888888888];
        y0 = [0.8888888888888888, 0.0];
    end


    methods(Static)
        % Upper-level objective function (quadratic)
        function val = F(x, y, ~)
            val = (x(1) - 1)^2 + 2*y(1)^2 - 2*x(1);
        end
        
        % Upper-level inequality constraints (bounds)
        function val = G(x, ~, ~)
            val = x;
        end
        
        % Upper-level equality constraints (none)
        function val = H(~, ~, ~)
            val = [];
        end
        
        % Lower-level objective function (quadratic)
        function val = f(x, y, ~)
            val = (2*y(1) - 4)^2 + (2*y(2) - 1)^2 + x(1)*y(1);
        end
        
        % Lower-level inequality constraints (linear)
        function val = g(x, y, ~)
            val = [
                -4*x(1) - 5*y(1) - 4*y(2) + 12;
                +4*x(1) + 5*y(1) - 4*y(2) - 4;
                -4*x(1) + 4*y(1) - 5*y(2) + 4 ;
                +4*x(1) - 4*y(1) - 5*y(2) + 4 ;
                y(1);
                y(2)
            ];
        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', 2, ...
                'F', 1, ...
                'G', 1, ...
                'H', 0, ...
                'f', 1, ...
                'g', 6, ...
                'h', 0 ...
            );
            if isKey(n,key)
                n = n(key);
            end
        end
    end
end