Generate the tuning function in FuzzyLD: "function_handle input" error

Hello,
I’ve been using the Fuzzy Logic Designer to tune some FIS systems for a few weeks, and it’s been working well—my cost function performs as expected, and my Simulink system gives great results.
However, I’d like to access and modify the tuning process (as: Log specific iterations during tuning or interrupt the process at a specific time to ensure consistent processing time across different configurations).
To achieve this, I tried generating the tuning function directly through the Designer app. However, I encountered the following error:
"Function is not defined for 'function_handle' inputs."
Knowing that I have the following settings:
And I am using the following custom cost function:
function [cost] = no_overshoot_cost(fis)
% I pass the FIS as variable for the workspace so that I can access it in
% my simulink system
assignin('base', 'fis_test', fis);
%I use a simulink to simulate my system
anz = sim("Fuzzy_PID");
signal = anz.Output;
% Extract data and time from both signals
step_data = anz.Input.Data;
output_data = signal.Data;
time = anz.Input.Time;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
overshoot = trapz(time, pos_error_signal); % Integrate the positive error
% undeshoot (output signal is above step input)
neg_error_signal = min(error_signal, 0); % Take only negative errors
undershoot = -trapz(time, neg_error_signal); % Integrate the negative error
% I don't want any overshoot so I penalise if any
if overshoot > 0
cost = 10;
else
cost = undershoot;
end
From what I understand, the error occurs because a function cannot accept another function as an input when using a variable function_handle, I assume that it is about the cost function but I am unsure
To address this, I modified the cost function, as I was previously using a separate function to compute the undershoot and overshoot. However, despite this change, the same error persists.
Would you have any idea how to resolve this error to let me get the tunning code ?
Thanks in advance,

4 Commenti

This is not a solution yet, but rather a prompt for you to consider the logic behind your engineering design.
Before tuning your fuzzy system, you should test whether your designed cost function is effective. Here is a very simple toy model (mass-damper-spring) that utilizes your cost function to tune a single parameter, C (damping) in the system.
Case 1: Before tuning with genetic algorithm
% System
M = 1; % mass
C = 0.5; % damping coefficient
K = 1; % spring stiffness
sys = tf(K, [M, C, K]) % C < 2 is underdamped, C > 2 is overdamped
sys = 1 --------------- s^2 + 0.5 s + 1 Continuous-time transfer function.
stepinfo(sys)
ans = struct with fields:
RiseTime: 1.2687 TransientTime: 14.1159 SettlingTime: 14.1159 SettlingMin: 0.8027 SettlingMax: 1.4432 Overshoot: 44.3235 Undershoot: 0 Peak: 1.4432 PeakTime: 3.3157
% Output signal
t = 0:0.01:25;
u = zeros(length(t), 1);
u(t>=0) = 1;
[y, t] = lsim(sys, u, t);
plot(t, [y, u]), grid on
legend('Output', 'Step input')
xlabel('Time (seconds)')
ylabel('Output Amplitude')
title('Time Response of Output signal')
% Extract data and time from both signals
step_data = 1;
output_data = y;
time = t;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
plot(t, error_signal), grid on
xlabel('Time (seconds)')
ylabel('Error Amplitude')
title('Time Response of Error signal')
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
plot(t, pos_error_signal), grid on
xlabel('Time (seconds)')
ylabel('Positive Error Amplitude')
title('Time Response of Positive Error signal')
overshoot = trapz(time, pos_error_signal) % Integrate the positive error
overshoot = 1.1222
Case 2: After tuning with genetic algorithm
The optimal damping value for a critically damped system should be 2. Each time you run the optimizer, it may return a value that is either close to the optimal value or relatively far from it within the range . This inconsistency suggests that you should revisit the logic of the cost function.
However, if your goal is simply to achieve a no-overshoot system, then the code for the cost function is acceptable.
lb = 1; % lower bound value of search range
ub = 3; % upper bound value of search range
C = ga(@no_overshoot_cost, 1, [], [], [], [], lb, ub)
ga stopped because the average change in the fitness value is less than options.FunctionTolerance.
C = 2.7787
% System
% C = 2; % Optimal damping value should be 2 (for a critically-damped system)
sys = tf(K, [M, C, K]) % C < 2 is underdamped, C > 2 is overdamped
sys = 1 ----------------- s^2 + 2.779 s + 1 Continuous-time transfer function.
stepinfo(sys)
ans = struct with fields:
RiseTime: 5.3177 TransientTime: 9.6768 SettlingTime: 9.6768 SettlingMin: 0.9009 SettlingMax: 0.9990 Overshoot: 0 Undershoot: 0 Peak: 0.9990 PeakTime: 16.7864
% Output signal
t = 0:0.01:25;
u = zeros(length(t), 1);
u(t>=0) = 1;
[y, t] = lsim(sys, u, t);
plot(t, [y, u]), grid on
legend('Output', 'Step input')
xlabel('Time (seconds)')
ylabel('Output Amplitude')
title('Time Response of Output signal')
% Extract data and time from both signals
step_data = 1;
output_data = y;
time = t;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
plot(t, error_signal), grid on
xlabel('Time (seconds)')
ylabel('Error Amplitude')
title('Time Response of Error signal')
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
plot(t, pos_error_signal), grid on
xlabel('Time (seconds)')
ylabel('Positive Error Amplitude')
title('Time Response of Positive Error signal')
overshoot = trapz(time, pos_error_signal) % Integrate the positive error
overshoot = 0
%% Cost function
function cost = no_overshoot_cost(C)
% System
sys = tf(1, [1, C, 1]);
% Output signal
t = 0:0.01:25;
u = zeros(length(t), 1);
u(t>=0) = 1;
[y, t] = lsim(sys, u, t);
% Extract data and time from both signals
step_data = 1;
output_data = y;
time = t;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
overshoot = trapz(time, pos_error_signal); % Integrate the positive error
cost = overshoot;
end
Additionally, the reason your cost function performs as expected is that the optimizer merely finds a set of values within the 'no-overshoot' mathematical set for the fuzzy system.
This can be analogously compared to instructing a friend to find a path in this region that goes from Point A to Point B in less than 10 minutes, even though your friend is unaware of the shortest path between these two points.
Hello @Sam Chak,
I have alredy tested my cost function directly auto-tunning in the Fussy Logic Designer, and it gave me proper results.
My cost function is indeed returning a single cost value (a simple real number). If your point in the second message is that I’m not optimizing the learning process, I completely agree—I’m currently using a brute-force approach.
I do not have comprehensive knowledge of fuzzy logic in MATLAB. Returning to your question, how are you able to pass the fuzzy inference system (FIS) object as a parametric variable in the cost function for your optimizer to tune?
Is the no_overshoot_cost(fis) an embedded function within a function that creates the FIS object?
%% Main Cost function
function cost = actual_cost(param)
fis = mamfis("Name", ...);
fis = addInput(fis, ...);
fis = addMF(fis, "...", "gaussmf", [param(1), param(2)], "Name", ...);
fis = addOutput(fis, ...);
fis = addMF(fis, "...", "trimf", [param(4), param(4), param(5)], "Name", "...");
ruleList = ...;
fis = addRule(fis, ruleList);
...
cost = no_overshoot_cost(fis);
%% sub-Cost function
function [cost] = no_overshoot_cost(fis)
assignin('base', 'fis_test', fis);
...
end
end

Accedi per commentare.

Risposte (0)

Categorie

Prodotti

Release

R2024b

Richiesto:

il 22 Dic 2024

Commentato:

il 23 Dic 2024

Community Treasure Hunt

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

Start Hunting!

Translated by