Unable to perform assignment because the left and right sides have a different number of elements, error

2 views (last 30 days)
Hello guys,
I have a code in Matlab. The code is about a genetic algorithm that tried to find 9 parameters a1..a4 and b1...b5 related to the function below:
The code has a main script and a data set provided, and then 6 different function files. The data set is constituted of a matrix with 101 rows and 2 columns, with the first column being different x values and the second column being g(x) values. The first function file should initialise a random population for the algorithm. The population basically contains a number of vectors and each vector represents a chromosome and contains random values for the a and b elements. In other words, each vector has 9 elements in it. The second function file should decode the chromosomes and provide a vector that contains a elements and another vector that contains b elements, but the elements in these vectors should now be scaled to a range of [-2,2). The third function file should provide the fitness value in the following way:
First the error should be compute: with obtained using the 9 parameters specified by the chromosomes and obtained with the first two function files and obtained with the data set provided.
The then fitness can be computed by: fitness=exp(-e) in such way that the fitness should be 0 < f <= 1.
The fourth function file, without going into much detail now, should perform a tournament selection with tournament size 2, the fifth function should perform a a single-point crossover and the last function file should carry out a mutation.
I have written all the function fils and when I run the code from the main script, I get the error provided in the title:
Unable to perform assignment because the left and right sides have a different number of elements, error.
Now, I know what this error means as I have encountered it several times before. However, I've tried several things to fix it but it keeps coming, that is because I lack a deep understanding of how Matlab and coding in general works. More explanation will come below as to where I am getting the code. Below is the main script, here there shouldn't be any error as it is provided.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% For problem 2.3, you must implement the following functions,
% with input parameters *exactly* as specified.
%
% (1) InitializePopulation(populationSize, numberOfParameters)
% This function should generate the population as a matrix with # rows = populationSize
% and # columns = numberOfParameters. Each gene (matrix element) should take a
% value in the range [0,1) (decimal values, not integers. Use the rand function!)
%
% (2) DecodeChromosome(chromosome, maximumParameterValue)
% This function should take a chromosome (= a vector with numbers in the range [0,1))
% and return the parameter vector a with p elements, where p is the polynomialDegree)
% and the parameter vector b (p+1 elements). The length of chromosome will thus be 2p+1.
% The elements should be in the specified range, i.e. [-maximumParameterValue, maximumParameterValue).
% Note that a and b are decimal numbers, not integers (even though they can, of course,
% take integer values, as a special case, in principle).
%
% (3) EvaluateIndividual(a, b, functionData)
% This function should generate (as output) the fitness value; see the problem
% formulation for details. Note: It is not always a good idea to pass a data
% set as a parameter, but here the data set is small, so it is OK.
%
% (4) TournamentSelect(fitness, tournamentProbability)
% This function should carry out tournament selection (with tournament size = 2)
% with the given value of pTour, and return the index of a single selected individual.
%
% (5) Cross(chromosome1, chromosome2)
% This function should carry out single-point crossover, with a randomly selected
% crossover point, and return a pair of new (offspring) individuals.
%
% (6) Mutate(originalChromosome, mutationProbability, creepProbability, creepRate)
% This function should carry out mutations, by running through all genes in the
% original chromosome, checking whether or not the gene should be mutated. If yes,
% apply either (with probability 1-pCreep) a full-range mutation or (with probability pCreep)
% a creep mutation with the specified creep rate. Then return the mutated chromosome.
% Note that genes take values in the range [0,1) (decimal numbers, not integers!)
%
% Also: implement a plot, showing the maximumFitness as a function of the number of generations.
% You must therefore add code (below) for storing the maximumFitness (i.e. a vector of values,
% one for each generation).
%
% Follow the coding standard. Note that, when the identity of a variable is evident from
% the context (as in the case of the vectors a and b), it is OK to use short variable
% names.
%
%
polynomialDegree = 4; % p (do not change)
populationSize = 100; % modify as desired (but should be even)
numberOfGenerations = 1000000; % modify as desired
maximumParameterValue = 2; % parameters range from -2 to 2 (do not change)
tournamentProbability = 0.75; % modify as desired
crossoverProbability = 0.75; % modify as desired
mutationProbability = 0.125; % modify as desired
creepProbability = 0.5; % modify as desired
creepRate = 0.01; % modify as desired
functionData = LoadFunctionData;
format long
numberOfParameters = 2*polynomialDegree+1;
aBest = zeros(polynomialDegree-1, 1); %% Best values of the a_i parameters
bBest = zeros(polynomialDegree, 1); %% Best values of the b_i parameters
maximumFitness = 0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialize population
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
population = InitializePopulation(populationSize, numberOfParameters);
fitness = zeros(populationSize,1);
maximumFitness = 0.0;
for iGeneration = 1:numberOfGenerations
maximumFitnessInCurrentGeneration = 0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Evaluate individuals
%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i = 1:populationSize
chromosome = population(i,:);
[a, b] = DecodeChromosome(chromosome,maximumParameterValue); %% Write this function
%% OK to use "a" and "b" here - evident from context what they mean.
fitness(i) = EvaluateIndividual(a,b,functionData); %% Write this function
if (fitness(i) > maximumFitnessInCurrentGeneration)
maximumFitnessInCurrentGeneration = fitness(i);
iBestIndividual = i;
if (fitness(i) > maximumFitness)
maximumFitness = fitness(i);
aBest = a;
bBest = b;
fprintf('%d %12.8f\n',iGeneration, maximumFitness);
end
end
end
%% Add plot of maximum fitness, either here or at the end of the
%% run. In the latter case, at least make sure to store the
%% maximum fitness for each generation, so that you can later make the plot.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Generate new population, unless the last generation has been evaluated
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if (iGeneration < numberOfGenerations)
temporaryPopulation = population;
for i = 1:2:populationSize
i1 = TournamentSelect(fitness,tournamentProbability); %% Write this function
i2 = TournamentSelect(fitness,tournamentProbability); %% Write this function
r = rand;
if (r < crossoverProbability)
chromosome1 = population(i1,:);
chromosome2 = population(i2,:);
newIndividualPair = Cross(chromosome1, chromosome2); %% Write this function
temporaryPopulation(i,:) = newIndividualPair(1,:);
temporaryPopulation(i+1,:) = newIndividualPair(2,:);
else
temporaryPopulation(i,:) = population(i1,:);
temporaryPopulation(i+1,:) = population(i2,:);
end
end
temporaryPopulation(1,:) = population(iBestIndividual,:); %% Elitism, prevents maximum fitness from decreasing.
for i = 2:populationSize
originalChromosome = temporaryPopulation(i,:);
mutatedChromosome = Mutate(originalChromosome, mutationProbability,creepProbability,creepRate); %% Write this function
temporaryPopulation(i,:) = mutatedChromosome;
end
population = temporaryPopulation;
end
end
Unable to perform assignment because the left and right sides have a different number of elements.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Here, you should add printout of the
% final results, i.e. aBest, and bBest,
% the minimum error etc., nicely formatted,
% as well as a plot of the maximumFitness
% as specified above.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Now the function file where I am getting the error will be attached here.
""Unable to perform assignment because the left and right sides have a different number of elements.
Error in GAFunctionFinder (line 88)
fitness(i) = EvaluateIndividual(a,b,functionData); %% Write this function""
The error points me to the main acript, but since I know there is no error in the main file, I know the error is situated in the third function file below (the one that computes the fitness, as discussed above). That is since, the line Matlab is referring to takes the output of the function provided. I have also included all the function files and main script attached, in case anyone finds it interesting enough to play with the code.
So, if anyone has any recommendations, it would be greatly appreciated! :)
function out3=EvaluateIndividual(e,f,functionData)
g=functionData(:,2);
x=rand*size(g);
sum1=0;
%func=0;
for i=1:length(x)
func=((((1+(e(1).*x)+(e(2).*x.^2)+(e(3).*x.^3)+(e(4).*x.^4))./(f(1)+(f(2).*x)+(f(3).*x.^2)+(f(4).*x.^3)+(f(5).*x.^4)))-g).^2);
%func(i)=((((1+(e(1).*x(i))+(e(2).*x(i).^2)+(e(3).*x(i).^3)+(e(4).*x(i).^4))./(f(1)+(f(2).*x(i))+(f(3).*x(i).^2)+(f(4).*x(i).^3)+(f(5).*x(i).^4)))-g(i)).^2);
%func(i+1)=((((1+(e(1).*x(i+1))+(e(2).*x(i+1).^2)+(e(3).*x(i+1).^3)+(e(4).*x(i+1).^4))./(f(1)+(f(2).*x(i+1))+(f(3).*x(i+1).^2)+(f(4).*x(i+1).^3)+(f(5).*x(i+1).^4)))-g(i+1)).^2);
sum1=sum1+func;
e=sqrt((1/101).*sum1);
out3=exp(-e);
if sum1==0
out3=1;
elseif out3>0
break
end
end
end

Answers (1)

Cris LaPierre
Cris LaPierre on 30 Aug 2022
Edited: Cris LaPierre on 30 Aug 2022
The output of EvaluateIndividual(a,b,functionData) is a 101x2 array. You are trying to assign this to a single element of fitness with the code fitness(i).
fitness must either be a cell array, or your assignment must include the same number of rows and columns as the output of your function.
Your code is written assuming the output is a dobule scalar value, so you may need to check that the output of EvaluateIndividual is what you expected.
% Works because left and right are the same size
a(1) = 5;
% Error because left and right are different sizes
a(2) = 1:3;
Unable to perform assignment because the left and right sides have a different number of elements.
  2 Comments
Christian Tsobanoglou
Christian Tsobanoglou on 30 Aug 2022
Thank you for the answer! Exactly, I am trying to get the output as a one cell array to attributed to a single fitness(i).
I added an "i" to line 10 in the function file and now it's: "sum1=sum1+func(i);"
However I get a new error now, as follows:
Index exceeds the number of array elements (1).
Error in EvaluateIndividual (line 7)
func=((((1+(e(1).*x(i))+(e(2).*x(i).^2)+(e(3).*x(i).^3)+(e(4).*x(i).^4))./(f(1)+(f(2).*x(i))+(f(3).*x(i).^2)+(f(4).*x(i).^3)+(f(5).*x(i).^4)))-g(i)).^2);
Any ideas? If I am not bothering much.
Cris LaPierre
Cris LaPierre on 31 Aug 2022
func only has one value, so when i>1, you get this error.
a=5;
% works
a(1)
ans = 5
% New error
a(2)
Index exceeds the number of array elements. Index must not exceed 1.
If you want a cell array, try using curly braces in your assignment
fitness{i} = EvaluateIndividual(a,b,functionData);
However, this will necessitate making changes to the downstream code, as it will not work with a cell array.

Sign in to comment.

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!