How to randomly generating a function with math operators and operands

9 visualizaciones (últimos 30 días)
Hi, I am new in matlab. Currently, I am trying to generate random functions with math operators like {+,-,*,/} and operands like {1,2,3,4}. Now I have a cell containing the operators I need. First of all, as the operators are in a cell, how can I use them to generate functions? Also, How can I randomly combine the operators and operands to generate functions? I would appreciate it a lot if someone could help me. Thanks Julie
  1 comentario
James Tursa
James Tursa el 29 de Jul. de 2017
By "functions", do you mean you want to randomly generate simple expressions with binary operators? E.g., generate expressions like 2*3 or 4/2 randomly? And do you want the result to be a string?

Iniciar sesión para comentar.

Respuesta aceptada

John BG
John BG el 30 de Jul. de 2017
Hi Julie
the answer to your question has 2 parts, 1st the random generation of operands operators, and the 2nd part the function engine that solves the random chains and supplies the results.
Part I
random generation of operands operators
clear all;clc;close all
format long;format compact
ops={'+' '-' '/' '*'} % operators
data=[1:1:9]
amount_ops=6
reps=10 % repetitions
ops_a_do=ops([randi([1 numel(ops)],reps,amount_ops)])
operands=data(randi([1 numel(data)],reps,amount_ops+1))
R=cell(reps,2*amount_ops+1)
for k=1:1:amount_ops+1
for s=1:1:reps
R{s,2*k-1}=operands(s,k)
end
end
for k=1:1:amount_ops
for s=1:1:reps
R{s,2*k}=ops_a_do{s,k}
end
end
R =
10×13 cell array
[3] '/' [2] '*' [9] '+' [3] '+' [1] '-' [3] '-' [4]
[2] '*' [6] '+' [8] '/' [3] '+' [2] '+' [4] '/' [2]
[6] '*' [6] '-' [8] '/' [5] '*' [6] '-' [5] '/' [2]
[6] '*' [1] '*' [5] '/' [6] '-' [3] '+' [7] '-' [9]
[4] '+' [9] '/' [2] '*' [1] '*' [9] '+' [8] '/' [7]
[2] '*' [7] '*' [4] '*' [8] '+' [2] '+' [1] '-' [5]
[9] '/' [7] '/' [2] '*' [6] '/' [9] '+' [2] '+' [9]
[1] '*' [1] '/' [1] '/' [8] '/' [5] '+' [4] '-' [1]
[1] '/' [8] '+' [9] '*' [4] '+' [7] '+' [1] '*' [7]
[2] '-' [9] '/' [3] '/' [5] '/' [9] '/' [5] '*' [7]
Part II
Calculation of results, the engine of the function
R2=NaN([reps 1],'double')
for s=1:1:reps
L=R(s,:)
r0=L{1}
for k=1:1:(length(L)-1)/2
L1=L([2*k-1:1:2*k+1])
op_=L1{2}
L1{1}=r0
switch op_
case ops{1} % +
r0=r0+L1{3}
case ops{2} % -
r0=r0-L1{3}
case ops{3} % /
r0=r0/L1{3}
case ops{4} % *
r0=r0*L1{3}
otherwise
disp('op error');
end
end
R2(s)=r0
end
R2 =
10.5000
6.3333
14.3000
0
9.5000
446.0000
11.4286
3.0250
311.5000
-0.0726
the presentation may be required in rational format
rat(R2)
=
10×20 char array
'11 + 1/(-2) '
'6 + 1/(3) '
'14 + 1/(3 + 1/(3)) '
'0 '
'10 + 1/(-2) '
'446 '
'11 + 1/(2 + 1/(3)) '
'3 + 1/(40) '
'312 + 1/(-2) '
'-0 + 1/(-14 + 1/(4))'
the function itself
  • requires safe checks of the inputs,
  • ranges instead of a cell may be preferred for the input of the operands,
  • and both R, the matrix containing operators and data, as well as the data may be required to be stored in separate files, so you can distribute the R without revealing R2.
You may want the function to return error codes, include time stamps and for instance generate a hash code combining different factors to verify authenticity. Fields for date, author, learning centre, class and distribution list may be also be desired.
It may be also desired to encrypt generated the operators operands matrix as well as the results, and do not disclose until just before exam start time.
At this point the question is solved, leaving the 'chassis' of the function at your discretion.
if you find this answer useful would you please be so kind to consider marking my answer as Accepted Answer?
To any other reader, if you find this answer useful please consider clicking on the thumbs-up vote link
thanks in advance
John BG
  8 comentarios
John BG
John BG el 1 de Ag. de 2017
Danke schön Jan for pointing out there's room for doubt.
In any case, let's wait for Julie to decide, either approach can be implemented with Stephen's script, or with my script. Even both ways can be easily implemented allowing the user to decide.
However in my opinion it's important for Stephen to consider Julie's line
'Now I have a cell containing the operators I need'
And Julie also writes '{' '}' to list the operators so far considered.
So Stephen should use a cell, not a string, for the operators.
Regards
John BG
John BG
John BG el 2 de Ag. de 2017
following, answer including both modes, speed test, or standard arithmetic.

Iniciar sesión para comentar.

Más respuestas (2)

Stephen23
Stephen23 el 30 de Jul. de 2017
Editada: Stephen23 el 1 de Ag. de 2017
This is MATLAB, so there is no point in writing slow and ugly nested loops and using switch statements when vectorized code and indexing is so much simpler and easier. The initial question does not specify very clearly what the output should be, so I read the title "...generating a function..." literally and return function handles with randomly generated sequences of the operators: {+,-,*,/}. This simple code should get you started: you can easily adapt it to your needs.
opr = '+-*/'; % binary operators
trm = 3; % number of operands
xpr = 4; % number of expressions
% pick random operators:
ido = randi(numel(opr),xpr,trm);
vec = 'a'+(0:trm);
% create expressions:
tmp = repmat('X',xpr,trm*2+1);
tmp(:,2:2:end) = opr(ido);
tmp(:,1:2:end) = ones(xpr,1)*vec;
tmp = num2cell(tmp,2);
% generate functions:
pfx = sprintf(',%c',vec);
pfx = sprintf('@(%s)',pfx(2:end));
out = strcat(pfx,tmp);
out = cellfun(@str2func,out,'Uni',0);
The randomly generated expressions are shown in the variable tmp:
>> tmp
tmp =
'a-b*c-d'
'a/b-c-d'
'a*b/c-d'
'a+b+c/d'
and the corresponding anonymous functions are stored in the cell array out:
>> out
out =
@(a,b,c,d)a-b*c-d
@(a,b,c,d)a/b-c-d
@(a,b,c,d)a*b/c-d
@(a,b,c,d)a+b+c/d
This allows us to easily test the output ourselves:
>> out{1}(1,2,3,4) % the first function
ans =
-9
>> 1-2*3-4 % the first expression
ans =
-9
Edit use this simple version for a cell array of binary operators:
opr = {'+','-','.*','./'}; % binary operators
trm = 3; % number of operands
xpr = 4; % number of expressions
% pick random operators:
ido = randi(numel(opr),xpr,trm);
vec = char('a'+fix(0:0.5:trm));
% create expressions:
tmp = repmat(num2cell(vec),xpr,1);
tmp(:,2:2:end) = opr(ido);
tmp = cellfun(@(c)[c{:}],num2cell(tmp,2),'uni',0);
% generate functions:
pfx = sprintf(',%c',vec(1:2:end));
pfx = sprintf('@(%s)',pfx(2:end));
out = strcat(pfx,tmp);
out = cellfun(@str2func,out,'Uni',0);
It has exactly the same outputs: out is a cell array of functions handles, and tmp shows the randomly constructed expressions.
  2 comentarios
John BG
John BG el 30 de Jul. de 2017
Stephen
if you don't use a cell to contain the operators list, you limit the operators to single characters, which in turn means that you cannot name operators with thinks like
sqr
or
sqrt
or
^3
John BG
Stephen23
Stephen23 el 31 de Jul. de 2017
Editada: Stephen23 el 1 de Ag. de 2017
@John BG: yes, I am aware that the code I wrote only works with single character binary operators. It is trivial to alter the code to use a cell array of binary operators, and change the anonymous functions to suit. Given the very vague specifications there is no point in making more code more complex than it needs to be for the given specifications.
"...which in turn means that you cannot name operators with thinks like sqr or sqrt or ^3"
Agreed. That is because I wrote the code to fit the specifications given in the question. Note that your code also cannot handle unary operators, so your list of non-parsed operators equally applies to your answer as well. Writing a parser that can handle unary and binary operators in any sequence is not trivial task.
PS: I could not find the sqr operator in the list of MATLAB functions. Can you please show a reference for it?

Iniciar sesión para comentar.


John BG
John BG el 2 de Ag. de 2017
Editada: John BG el 2 de Ag. de 2017
Hi Julie
the following script generates an amount of ops_a_do operations using the operands listed in cell ops, repeating reps times.
  • When variable speed_contest=1 the script skips parentheses. For instance 1+2*3 = (((1+2))*3)=9
  • if speed_contest=0, then 1+2*3=7
The inputs
clear all;clc;close all
format long;format compact
ops={'+' '-' '/' '*'} % operators
data=[1:1:9]
amount_ops=6
reps=10 % repetitions
speed_contest=0 % choose, 1: 1+2*3 = (((1+2))*3)=9 2: 1+2*3=7
the basic function
function [R,R2]=gen_ops(ops,data,amount_ops,reps,speed_contest)
ops_a_do=ops([randi([1 numel(ops)],reps,amount_ops)])
operands=data(randi([1 numel(data)],reps,amount_ops+1))
R=cell(reps,2*amount_ops+1)
for k=1:1:amount_ops+1
for s=1:1:reps
R{s,2*k-1}=operands(s,k)
end
end
for k=1:1:amount_ops
for s=1:1:reps
R{s,2*k}=ops_a_do{s,k}
end
end
R
% Calculation of results
R2=NaN([reps 1],'double')
switch speed_contest
case 1 % speed test on, 1+2*3 = (((1+2))*3)=9
for s=1:1:reps
L=R(s,:)
r0=L{1}
for k=1:1:(length(L)-1)/2
L1=L([2*k-1:1:2*k+1])
op_=L1{2}
L1{1}=r0
switch op_
case ops{1} % +
r0=r0+L1{3}
case ops{2} % -
r0=r0-L1{3}
case ops{3} % /
r0=r0/L1{3}
case ops{4} % *
r0=r0*L1{3}
otherwise
disp('op error');
end
end
R2(s)=r0
end
case 0 % speed test off, 1+2*3=7
for s=1:1:reps
L=R(s,:)
L2=[]
for k=1:1:length(L)
if ~ischar(L{k}) L2=[L2 num2str(L{k})]; end
if ischar(L{k}) L2=[L2 L{k}]; end
end
R2(s)=evalin('base',L2)
end
otherwise
disp('speed_contest var out of range error')
end
R2
end
if you find this answer useful would you please be so kind to consider marking my answer as Accepted Answer?
To any other reader, if you find this answer useful please consider clicking on the thumbs-up vote link
thanks in advance
John BG
  2 comentarios
Julie G
Julie G el 2 de Ag. de 2017
Hi John, Thanks a lot for your answer. It helped me a lot. Sorry for replying you so late as I did not work for some days. Actually, I am doing genetic programming with matlab, which I am really not very familiar with. Do you know anything about genetic programming in matlab, especially the toolbox "GP_OLS".
John BG
John BG el 2 de Ag. de 2017
Editada: John Kelly el 23 de Ag. de 2017
Hi Julie
Thanks for accepting my answer
A.-
I don't have experience with MATLAB applied to genetics, but I am aware that you can use MATLAB to compile data obtained from laboratory measurements, directly from the instruments, and then validate or improve whatever simulation or model you have.
B.-
Please note that some forum contributors had a bit of discussion about whether you wanted conventional arithmetic 1+2*3=7 or you were intending to use parentheses skipping, that is sometimes used in (human) speed competitions, where 1+2*3 really means ((1+2)*3)=9
Julie, for the sole purpose of clarifying this point, would you please be so kind to add a comment on this regard?
C.-
note that today I have added a very basic function that includes both arithmetic, with command evalin, and a simple manual switch with variable speed_contest.
D.-
Literature References that include, or may include related MATLAB code
Found the following links, perhaps you probably already have them all, then for the readers:
1.-
this journal, Genetic programming for the identification of nonlinear input-output models, by Madar, Abonyi, Szeifert
claims to have a freely available implementation in MATLAB that specifically mentions Genetic Programming and OLS estimation tools, follow this link
2.-
the book: Graph Based Clustering and Data Visualisation Algorithms, by Vathy-Fogarassy, Abonyi. Springer
has MATLAB examples are available for download in this page too.
3.-
Same for book: Cluster analysis for data mining and system identification, by Abonyi, Feil, Birkhäuser Verlag, has a Fuzzy Clustering and Data Analysis Toolbox
again MATLAB examples and toolbox detailed examples are freely available.
Regards
John BG

Iniciar sesión para comentar.

Categorías

Más información sobre Genetic Algorithm en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by