求兼容str2func的Matlab随机闭式表达式生成代码
生成兼容str2func的MATLAB闭式表达式字符串的解决方案
报错原因分析
你遇到的horzcat错误,核心问题是**funcSet里混合了匿名函数句柄和内置函数句柄**,而你的generateRandomExpr直接把函数句柄当字符串拼接——MATLAB无法将多输入的匿名函数句柄直接转换为字符,才会抛出“Too many output arguments”的错误。
修正方案
1. 重构函数集定义
不能直接存函数句柄,要换成函数名+参数个数的单元格结构,这样才能正确拼接表达式字符串:
funcSet = { {'add', 2}, {'sub', 2}, {'mul', 2}, {'div', 2}, {'pow', 2},... {'exp', 1}, {'log', 1}, {'sin', 1}, {'sinh', 1}, {'cos', 1}, {'cosh', 1}, {'tan', 1}, {'tanh', 1} }; terminalSet = {'z', 'a1', 'a2'}; % 支持多常数变量 maxDepth = 6; % 满足深度>4的要求
2. 重写generateRandomExpr函数
下面是递归生成符合要求的表达式字符串的代码,完全兼容str2func:
function expr = generateRandomExpr(currentDepth, funcSet, terminalSet) % 递归终止:深度为1时返回终端节点 if currentDepth == 1 expr = terminalSet(randi(length(terminalSet))); return; end % 随机选一个函数,获取名称和参数数 funcIdx = randi(length(funcSet)); funcName = funcSet{funcIdx}{1}; numArgs = funcSet{funcIdx}{2}; % 递归生成每个参数的表达式,控制子节点深度保证总深度>4 args = cell(1, numArgs); for i = 1:numArgs minChildDepth = max(1, currentDepth - 3); childDepth = randi([minChildDepth, currentDepth - 1]); args{i} = generateRandomExpr(childDepth, funcSet, terminalSet); end % 拼接成闭式表达式 switch funcName case {'add','sub','mul','div','pow'} expr = ['(' args{1} [{'+' '-' '*' '/' '^'}{strcmp(funcName, {'add','sub','mul','div','pow'})}] args{2} ')']; otherwise expr = [funcName '(' args{1} ')']; end end
3. 测试验证
调用函数并转换为可执行句柄:
% 生成表达式字符串 exprStr = generateRandomExpr(maxDepth, funcSet, terminalSet); disp('生成的表达式:'); disp(exprStr); % 转换为支持复变量的函数句柄 myFunc = str2func(['@(z,a1,a2) ' exprStr]); % 用复数值测试 testZ = 1+2i; testA1 = 3; testA2 = 0.5; result = myFunc(testZ, testA1, testA2); disp('测试结果:'); disp(result);
生成的表达式会自动混合有理运算、指数、对数、三角函数,且深度满足>4的要求,直接可用str2func转换为可调用的函数句柄。
可选:保留原函数句柄的映射方案
如果一定要用原函数句柄的定义方式,可以加一个映射层,把句柄对应到函数名:
funcHandleToName = containers.Map(... {@(z,a) z+a, @(z,a) z-a, @(z,a) z*a, @(z,a) z/a, @(z,a) z^a, @exp, @log, @sin, @sinh, @cos, @cosh, @tan, @tanh},... {'add', 'sub', 'mul', 'div', 'pow', 'exp', 'log', 'sin', 'sinh', 'cos', 'cosh', 'tan', 'tanh'});
之后在函数里通过这个映射获取函数名称即可,但这种方式不如直接存函数名+参数数直观。
内容的提问来源于stack exchange,提问作者Günter Bachelier
相关产品推荐
相关产品推荐

