How to randomly generating a function with math operators and operands
Show older comments
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 Comment
James Tursa
on 29 Jul 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?
Accepted Answer
More Answers (2)
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'
>> 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 Comments
John BG
on 30 Jul 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
@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?
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 Comments
Julie G
on 2 Aug 2017
John BG
on 2 Aug 2017
Edited: John Kelly
on 23 Aug 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
Categories
Find more on Genetic Algorithm in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!