I am using GA in Matlab to solve an optimization problem,
my objective function is to minimize cost with variable v,
function b = cost (v)
load ('data.mat');
c1=0;
for i = 1:N
for j=1:1
c1 = c1 + c(i,j)*v(i,j);
end
end
b=c1;
and my constraint is const
function [z] = const(v)
load ('data1.mat');
Z1=1;
for i=1:N
for j=1:1
a(i,j) = (1-v(i,j))*t(i,j);
Z(i,j) = ((a(i,j)+T1)/y(i,j))/(a(i,j)/y(i,j));
end
Z1 = Z1 * Z(i,j);
end
z=[0.7-Z1];
zeq=[];
Using for code for GA
lb=zeros(N,1);
ub=ones(N,1);
IntCon = u;
options = gaoptimset('PlotFcns',{#gaplotbestf,#gaplotmaxconstr},'Display','iter');
[v, fval] = ga(#cost,N,[],[],[],[],lb,ub,#const,IntCon,options);
where u=[1 2 3 4...N]
I have already saved required data in data1.mat file.
I want to make the objective function and constraint both generalized,
otherwise I will have to write R,a and c value for N number of times.
problem is when I run it, it gives a message
%Error using ga (line 342)
%Too many output arguments.
%Caused by:
%Failure in initial user-supplied nonlinear constraint function evaluation.
You need to use varargout which is variable output argument in MATLAB. Simply replace your code's output argument i.e. where you have defined your ga function. Instead of an array, it should be varargout{}. There is an example on Mathworks site about how to do this.
Possibly change your input and output arguments with varargin and varargout respectively. Seems like you will need this throughout.
hope this helps!
Related
I am trying to optimize a function in MATLAB which has a for-loop in it. I tried different codes but didn't get any results and can't figure out where is the problem.
here is the function:
function U2 = least1(ydata,xdata,x,y1,w,A,sz,yprime,y)
for i=1:1:1000
U2(1,i) = sum((sqrt(1+yprime.^2)).*(A(1) * exp(-y/A(2))*(1 - exp(-ydata(i)/A(2)))...
+ A(3) * exp(-y/A(4))*(exp(-ydata(i)/A(4))-1)).*w);
end
end
All the variables are available I just need to optimize it to get the perfect match of A.
I tried to solve it with the problem-based optimization as the codes below :
but instead of four values for A, I get
-Inf
-Inf
-Inf
-Inf
A = optimvar('A',4);
potential = fcn2optimexpr(#least1,A);
obj = sum((potential - u1).^2);
prob = optimproblem('Objective',obj);
x0.A = [11.959,0.069,3.53,4.118*10^(-3)];
show(prob)
sol = solve(prob,x0)
please let me know if anything is missing
The optimizer does not now what to do with the other inputs of least1(ydata,xdata,x,y1,w,A,sz,yprime,y).
You need to tell it the values when you assign it as a cost function, i.e.
#(A) least1(ydata,xdata,x,y1,w,A,sz,yprime,y)
The keyword is anonymous function handle (what you have just is just a function handle.
I am pretty irritated by the way you are setting up the optimization problem (maybe that is a new way?).
I would have made it straight forward this way:
% anonymous function handle to original function
fnc_ogl = #(A) least1(ydata,xdata,x,y1,w,A,sz,yprime,y) -u1;
% create least-squares cost function (you need to have a single cost value
% for fminsearch)
fnc_cst = #(A) sum( fnc_ogl.^2 );
% initial guess
A0 = [11.959,0.069,3.53,4.118*10^(-3)]
% call unconstrained local optimization
[A_opt, fval, exitflag] = fminsearch(fnc,A0)
BTW
you should allocate the size of U2 beforehand with U2 = NaN(1,1000) to speed up the cost function
Your example does not work as all inputs to least1 are missing
least1 does not use the variables xdata, x, y1, and sz
.
I have a function F which takes as an input a vector a. Both the output of the function and a are vectors of length N, where N is arbitrary. Each component Fn is of the form g(a(n),a(n-k)), where g is the same for each component.
I want to implement this function in matlab using its symbolic functionality and calculate its Jacobian (and then store both the function and its jacobian as a regular .m file using matlabFunction). I know how to do this for a function where each input is a scalar that can be handled manually. But here I want a script that is capable of producing these files for any N. Is there a nice way to do this?
One solution I came up with is to generate an array of strings "a0","a1", ..., "aN" and define each component of the output using eval. But this is messy and I was wondering if there is a better way.
Thank you!
[EDIT]
Here is a minimal working example of my current solution:
function F = F_symbolically(N)
%generate symbols
for n = 1:N
syms(['a',num2str(n)]);
end
%define output
F(1) = a1;
for n = 2:N
F(n) = eval(sprintf('a%i + a%i',n,n-1));
end
Try this:
function F = F_symbolically(N)
a = sym('a',[1 N]);
F = a(1);
for i=2:N
F(i) = a(i) + a(i-1);
end
end
Note the use of sym function (not syms) to create an array of symbolic variables.
I have some code here which illustrates the nested nature of some integrals that I want to perform in matlab. When I run the following code I get the error
Error using .*
Matrix dimensions must agree.
Error in fun1/integrand (line 7)
f = x.^2.*t;
it seems that the way I have set it up now does not allow for vectorized output of the integral function. What can I do to make my code run? I have commented below what I want the functions to do.
My code is as follows:
%Main script:
z = linspace(0,10,10);
I = zeros(10,1);
for i = 1:10
I(i) = fun2(z(i));
end
%Function 1 in separate file:
function I = fun1(x)
I = integral(#integrand,-1,1);
function f = integrand(t)
f = x.^2.*t;
end
end
%Function 2 in separate file:
function I = fun2(z)
I = integral2(#integrand,-1,1,-1,1);
function f = integrand(x,y)
f = z.*fun1(x).*y; // here fun1 should return the value for all x that is swept through by integral2 during its call.
end
end
The problem with your code is you are using integral2 and integral1 in a combination. This way integral2 generates a grid for x and y and integral1 generates the t values. This way the t and x values don't match in size, and even if they would they are part of a different grid.
As already discussed, using ingetral3 is the right choice. Alternatively you could simply "fix" this introducing a loop, but this results in much slower code:
function I = fun1(x)
I=nan(size(x));
for ix=1:numel(x)
I(ix) = integral(#(t)integrand(x(ix),t),-1,1);
end
function f = integrand(x,t)
f = x.^2.*t;
end
end
but i want to make a program in which i can generate a function of multiple variables that depend on the number of rows of a matrix.
for k = 1:sizel;
f(k)=(alpha(k,1)+(beta(k,1)*p(k))+(gamma(k,1)*p(k)^2));
end
cost=(sum(f))
this is for the purpose of optimization so i need that at the end the variables are declares as p(1),p(2),p(3)... these will be the input for my function.
Note: i dont want to assign values to the variables because this will be done be the optimization algorithm in the optimization toolbox.
here is the complete code
function cost = cost(p) ;
clc
clear
costfunctionconstantsmatrix;
sizel=size(CostFormulaconstants);
alpha=CostFormulaconstants(:,1);
beta=CostFormulaconstants(:,2);
gamma=CostFormulaconstants(:,3);
for k = 1:sizel;
f(k)=(alpha(k,1)+(beta(k,1)*p(k))+(gamma(k,1)*p(k)^2));
end
cost=(sum(f))
end
i used the symbolic approach and i got the correct answer for the cost indeed, i got something like this: (53*p(1))/10 + (11*p(2))/2 + (29*p(3))/5 + p(1)^2/250 + (3*p(2)^2)/500 + (9*p(3)^2)/1000 + 1100. But when i try to specify my function to be optimized in the optimization toolbox it tells me that the variables p are sym and cannot be converted to double. the trouble is how to convert this expression to double so that the optimization algorithm can input values for the variable p(1), p(2) and p(3)
Can you pass the matrix as an argument to the function?
function cost = fcn(my_mat)
[m,n] = size(my_mat);
f = zeros(m,1);
for k = 1:m % for example
f(k)=(alpha(k,1)+(beta(k,1)*p(k))+(gamma(k,1)*p(k)^2));
end
cost = sum(f);
end
Your problem is not entirely clear to me but I believe you wish to generate a series of functions in which the variables alpha, beta, gamma are constants with different values for each function, and the vector p is an argument.
What confuses me in your question is that you use the index k for both the constants and the arguments, which I think is not what you intended to write. Assuming I understand your goal, a solution may make use of function handles.
The notation f(k) = #(p) p(1)+p(2) for example, generates a function that adds p(1) and p(2). Abbreviating CostFormulaconstants to cf, the following would generate a series of functions, one for each row in cf.
for k = 1 : size(cf, 1)
f{k} = #(p) cf(k,1) + cf(k,2)*p(1) + cf(k,3)*p(2)^2;
end
You can supply individual function handles to callers from the optimization toolbox simply with f{3} for the third function, for example. A call to f{3} would look like
a = f{3}([3,4]);
If your functions are indeed all polynomials, polyval may be worth a look as well.
EDIT: After clarification, the problem seems a bit simpler, no need for function handles. Why not simply
function c = cost(p)
c = 0;
cf = [...]; % your coefficients here.
for k = 1 : size(cf, 1)
c = c + cf(k,1) + cf(k,2)*p(k) + cf(k,3)*p(k)^2;
end
I want to solve two nonlinear equations in MATLAB so i did the following:
part of my script
c=[A\u;A\v];
% parts of code are omitted.
x0=[1;1];
sol= fsolve(#myfunc,x0);
the myfunc function is as follows
function F = myfunc(x)
F=[ x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj];
end
i have two unknowns x(1) and x(2)
my question is How to pass a values(c,ii,jj) to myfunc in every time i call it?
or how to overcome this error Undefined function or method 'c' for input arguments of type 'double'.
thanks
Edit: The previous answer was bogus and not contributing at all. Hence has been deleted. Here is the right way.
In your main code create a vector of the coefficients c,ii,jj and a dummy function handle f_d
coeffs = [c,ii,jj];
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
sol = fsolve(f_d,x0);
Make your function myfunc capable of taking in 2 variables, x0 and coeffs
function F = myfunc(x, coeffs)
c = coeffs(1:end-2);
ii = coeffs(end-1);
jj = coeffs(end);
F(1) = x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
F(2) = x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj;
I think that should solve for x0(1) and x0(2).
Edit: Thank you Eitan_T. Changes have been made above.
There is an alternative option, that I prefer, if a function handle is not what you are looking for.
Say I have this function:
function y = i_have_a_root( x, a )
y = a*x^2;
end
You can pass in your initial guess for x and a value for a by just calling fsolve like so:
a = 5;
x0 = 0;
root = fsolve('i_have_a_root',x0,[],a);
Note: The [] is reserved for fsolve options, which you probably want to use. See the second call to fsolve in the documentation here for information on the options argument.