
client = jcmoptimizer.Client(); 

% Definition of the search domain
design_space = { ...
    struct('name', 'x1', 'type', 'continuous', 'domain', [-1.5,1.5]), ...
    struct('name', 'x2', 'type', 'continuous', 'domain', [-1.5,1.5]) ...
};

% Definition of fixed environment parameter
environment = {...     
   struct('name', 'radius', 'type', 'fixed', 'domain', 1.5) ...
};

% Definition of a constraint on the search domain
constraints = {...
   struct('name', 'circle', 'expression', 'sqrt(x1^2 + x2^2) <= radius')...
};

 % Creation of the study object with study_id 'scipy_minimization'
study = client.create_study( ...
    'design_space', design_space, ...
    'environment', environment, ...
    'constraints', constraints,...
    'driver','ScipyMinimizer',...
    'study_name','Gradient-based minimization of a non-expensive scalar function',...
    'study_id', 'scipy_minimization');

study.configure('max_iter', 30, 'num_initial', 6, 'jac', true, 'method', 'SLSQP');

% Evaluation of the black-box function for specified design parameters
function observation = evaluate(study, sample)

    observation = study.new_observation();
    observation.add(10*2 ...
                    + (sample.x1^2 - 10*cos(2*pi*sample.x1)) ...
                    + (sample.x2^2 - 10*cos(2*pi*sample.x2)) ...
                   );
    observation.add(2*sample.x1 + 2*pi*sin(2*pi*sample.x1), ...
                    'derivative', 'x1');
    observation.add(2*sample.x2 + 2*pi*sin(2*pi*sample.x2), ...
                    'derivative', 'x2');     
    
end  

% Run the minimization
study.set_evaluator(@evaluate);
study.run(); 

best = study.driver.best_sample;
fprintf('Best sample at x1=%0.3e, x2=%0.3e\n', best.x1, best.x2) 

client.shutdown_server();
