# Using the 'eval" function in parfor

20 views (last 30 days)
dsmalenb on 23 Jul 2016
Commented: dsmalenb on 27 Jul 2016
Greetings,
I am writing a piece of code that composes and evaluates logical expressions for my research. It picks one of the 26 minimally functionally complete operator sets, chooses the number of variables and then composes expressions based on those criteria.
I have worked on this problem for some time now and I have reluctantly used Matlab's 'eval' command to evaluate these logical expressions. Although I do have it working for the "in series" case, I have considerable difficulty expanding it to the "parallel" case.
I have provided my script and the necessary functions below. I have also commented the script so that (hopefully) you may follow along. As you will see, my difficulties arise in the following line:
ExpResult(1+jj,k) = eval(Syntax{k});
I have read quite a bit about the eval function and its limitations as well as the considerable disadvantages of using it while developing dynamic variables. I still feel that all things considered this particular methodology for this particular problem was still necessary. However, I could be incorrect in that assessment. At this point, my objective is to get a working version of this script and then modify. If you could assist in that effort, I would be very thankful.
The script is as follows:
% This script stochastically evaluates propositional formulas of arity-2
% It also evaluates based on a certain set of atoms.
% In addition, this script employs T and F as constants which is
% different than the previous versions.
clc; % Clear output screen
AtomNum = 5; % Number of variables used
AtomMax = 5; % Maximum number of variables (for later)
LL = 100; % Number of evaluations before save
syms G; % For rest of code
N = 100; % Number of iterations to run
R(1:N) = 0; % Initialize Random number dimensions
% Create generalized atoms instead of p, q, r, etc...
for j = 1:AtomMax
for k=1:N
Atom{j,k} = strcat('p(', num2str(j),',',num2str(k),')');
end
end
% Create CDFs
RV1(1,1:N) = rand(1,N); % Create an array of random variables to use
RV1(2,1:N) = RV1(1,1:N) + rand(1,N);
RV1(1,1:N) = RV1(1,1:N)./RV1(2,1:N);
RV1(2,1:N) = RV1(2,1:N)./RV1(2,1:N);
RV2(1,1:N) = rand(1,N); % Create an array of random variables to use
RV2(2,1:N) = RV2(1,1:N) + rand(1,N);
RV2(3,1:N) = RV2(2,1:N) + rand(1,N);
RV2(1,1:N) = RV2(1,1:N) ./RV2(3,1:N);
RV2(2,1:N) = RV2(2,1:N) ./RV2(3,1:N);
RV2(3,1:N) = RV2(3,1:N) ./RV2(3,1:N);
RV3(1,1:N) = zeros(1,N);
for j=2:AtomMax+1
RV3(j,1:N) = RV3(j-1,1:N) + rand(1,N);
end
for j=1:AtomMax+1
RV3(j,1:N) = RV3(j,1:N)./RV3(AtomMax+1,1:N);
end
% Initialize string variables
for j=1:N
Constant{j} = '';
Q{j} = '';
BString{j} = '';
str1{j} = '';
end
p(1:AtomMax,1:N) = zeros(AtomMax,N);
ExpResult(1:2^AtomMax,1:N) = 0;
% Distribute computations over many processors.
% 1) Create well-formed propositional formulas
% 2) evaluate formulas
% 3) store results
parfor k = 1:N
Syntax{k} = 'Z'; % Seed for all propositional formulas is a nondescript atom
VarCnt(k) = 1; % Number of variables within a formula are counted
W(k) = randi([0, 2^52]); % To ensure longer formulas are more included
W(k) = log(W(k))/log(2);
OperNum(k) = 1+ floor(W(k));
L(k) = randi([1,26]); % Randomly select which language to use
% There are 26 minimally functionally complete languages. Choose
% which one to use. Must be coded in this way.
switch L(k)
case 1 % {NAND}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
Syntax{k} = regexprep(Syntax{k},'Z','NAND(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
case 2 % {NOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
Syntax{k} = regexprep(Syntax{k},'Z','NOR(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
case 3 % {NOT, AND}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand; % <- shows up as [0,0,0,...0] in workspace
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','not(Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','and(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
end
case 4 % {NOT, OR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','not(Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','or(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
end
case 5 % {NLA, LA} Eigenanti
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','NLA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','LA(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 6 % {NRA, RA} Eigen Anti
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','NRA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','RA(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 7 % {NLA, RA} Eigen Reverse Bit Flip
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','NLA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','RA(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 8 % {NRA, LA} Eigen Reverse Bit Flip
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','NRA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','LA(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 9 % {LA, XOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','LA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','xor(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 10 % {RA, XOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','RA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','xor(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 11 % {NLA, NXOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','NLA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NXOR(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 12 % {NRA, NXOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','NRA(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NXOR(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 13 % {NOT,RA}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','not(Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','RA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
end
case 14 % {NOT,LA}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','not(Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','LA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
end
case 15 % {NOT,NRA}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','not(Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NRA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
end
case 16 % {NOT,NLA}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','not(Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NLA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
end
case 17 % {NLA, T}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
Syntax{k} = regexprep(Syntax{k},'Z','NLA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
case 18 % {NRA, T}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
Syntax{k} = regexprep(Syntax{k},'Z','NRA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
case 19 % {LA, F}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
Syntax{k} = regexprep(Syntax{k},'Z','LA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
case 20 % {RA, F}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
Syntax{k} = regexprep(Syntax{k},'Z','RA(Z,Z)', R(k));
VarCnt(k) = VarCnt(k) + 1;
end
case 21 % {AND, NXOR, F}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','and(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NXOR(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 22 % {OR, XOR, T}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','or(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','xor(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 23 % {AND, XOR, NXOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV2(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','and(Z,Z)', R(k));
elseif r <= RV2(2,k)
Syntax{k} = regexprep(Syntax{k},'Z','xor(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NXOR(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 24 % {OR, XOR, NXOR}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV2(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','or(Z,Z)', R(k));
elseif r <= RV2(2,k)
Syntax{k} = regexprep(Syntax{k},'Z','xor(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NXOR(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 25 % {AND, XOR, T}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','and(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','xor(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
case 26 % {OR, NXOR, F}
for jj = 1:OperNum(k)
R(k) = randi([1, VarCnt(k)]);
r = rand;
if r <= RV1(1,k)
Syntax{k} = regexprep(Syntax{k},'Z','or(Z,Z)', R(k));
else
Syntax{k} = regexprep(Syntax{k},'Z','NXOR(Z,Z)', R(k));
end
VarCnt(k) = VarCnt(k) + 1;
end
end
% For those languages which have TRUE or FALSE constants, we have an
if (L(k) >= 17 && L(k) <= 22) || L(k) == 25 || L(k) == 26
if L(k) == 17 || L(k) == 18 || L(k) == 22 || L(k) == 25
Constant{k} = '1';
else
Constant{k} = '0';
end
% Select which atom index to assign to each nondescript atom
for jj = 1:VarCnt(k)
for m = 1:AtomNum
r = rand;
if r >= RV3(m,k) && r < RV3(m+1,k)
Syntax{k} = regexprep(Syntax{k},'Z',Atom{m,k}, randi([1, VarCnt(k)-jj+1]));
end
end
end
Syntax{k} = regexprep(Syntax{k},'Z',Constant{k});
else
% Select which atom index to assign to each nondescript atom
for jj = 1:VarCnt(k)
for m = 1:AtomNum
r = rand;
if r >= RV3(m,k) && r < RV3(m+1,k)
Syntax{k} = regexprep(Syntax{k},'Z',Atom{m,k},randi([1, VarCnt(k)-jj+1]));
end
end
end
Syntax{k} = regexprep(Syntax{k},'Z',Atom{AtomNum,k});
end
% Just like in a truth table with multiple variables so too must we
% set up our variables to do the same thing.
for jj = 0:2^AtomNum-1
BString{k} = dec2bin(jj);
for n = 1:length(dec2bin(2^(AtomNum)-1))-length(dec2bin(jj))
BString{k} = strcat('0',BString{k});
end
p(:,k) = str2num(BString{k} (:));
% Up until this point everything works as it should. Each 'Syntax'
% is ready to be evaluated. The problem is actually evaluating it.
% Substitute 'p(*,k)' values w/actual values
ExpResult(1+jj,k) = eval(Syntax{k}); % <- This line is the issue
% Q = strcat(Q,num2str(ExpResult(1+j,1)));
end
% The rest of the routine is here. I left it out since it is not
% necessaey
end
Also, the necessary functions are below. They are the remaining Boolean functions of arity 2 which are not standard Matlab functions:
function [V] = NOR(p,q)
V = not(or(p,q));
end
function [V] = NAND(p,q)
V = not(and(p,q));
end
function [V] = LA(p,q)
V = or(not(xor(p,q)),not(p));
end
function [V] = NLA(p,q)
V = and(xor(p,q),p);
end
function [V] = NRA(p,q)
V = and(xor(p,q),not(p));
end
function [V] = RA(p,q)
V = or(not(xor(p,q)),p);
end
function [V] = NXOR(p,q)
V = not(xor(p,q));
end

dsmalenb on 26 Jul 2016
Made quite some progress I think. Finally found a case where the eval function will not create an error. However not sure how to generalize the code. Made the following modifications:
1) Set the following variables at the top:
AtomNum = 3; % Number of variables used
AtomMax = 3; % Maximum number of variables (for later)
2) Redefine ExpResult
ExpResult = cell(1,N);
for i=1:N
ExpResult{1,N}(1:2^AtomMax,1)=0;
end
3) Strip out the follwing line:
p(:,k) = str2num(BString{k} (:));
4) Set the following static variables (for the Atom = 3 case only):
q1 = str2num(BString{k} (1));
q2 = str2num(BString{k} (2));
q3 = str2num(BString{k} (3));
5) Set the ExpResult line to:
ExpResult{k,1}(1+jj,1) = commitEval(Syntax{k},k,q1,q2,q3);
6) Edit the commitEval function as:
function [D] = commitEval(Syntax,k,q1,q2,q3)
p(1,k) = q1;
p(2,k) = q2;
p(3,k) = q3;
D = eval(Syntax);
end
Now the script will run and I think as it should. However it will only run in this specific '3' case. I have tried to generalize using arrays, etc but it won't take. I am not sure why.
Any ideas? Almost there...
jgg on 27 Jul 2016
If the error is the same (``undefined variable'') then I'm 99% sure you can fix it by simply passing ALL of the possible inputs to the function being created by eval into the commitEval function.
This may be a bit cumbersome to code as above, so try passing them as a struct instead.
Basically, if I understand what is going is as follows:
1) Your eval command creates a function and a function call together. It's like eval(strcat('sin(','x',')')) for example. This part appears to be working properly.
2) The issue seems to be that the function call created is sin(x) and within the commitEval() function the variable x is unknown.
3) The solution is then to pass all possible x's into your commitEval function. This is troublesome since there are a lot of possible inputs, but I don't think it's impossible.
You also might be able to get creative and pass only the ones you need, but that seems like the solution.
See if that works! If you get an error, let me know what it is precisely.
Your solution to the classification problem is correct, though. Good work.
dsmalenb on 27 Jul 2016
jgg,
Script is running and finally works. Thank you for your help!