%% =======================================================================
%
%  Hybrid ANN–ODE–FODE Modeling of PISA Scores (Turkey)
%  - Reads data from Supplementary_Data.xlsx
%  - Trains ANN with tansig activation (9–9–3 architecture)
%  - Computes performance metrics (RMSE, SSE, R²) for:
%       * Only real PISA cycles (2009, 2012, 2015, 2018, 2022)
%       * All augmented annual data (2009–2023)
%  - Simulates ODE / FODE system using pisa_function_frac.m
%  - Compares integer-order ODE vs fractional orders (FODE)
%
%  All outputs, messages, and comments are in English for transparency.
% ========================================================================

close all; clear; clc;

%% -----------------------------------------------------------------------
%  1) File and sheet names
% ------------------------------------------------------------------------
dataFile = 'Supplementary_Data.xlsx';

% Sheet 1: Original PISA cycles + inputs (real observations only)
sheetOriginal    = 'Original_Data';

% Sheet 2: Linearly interpolated annual dataset (Table 4 in manuscript)
sheetAnnual      = 'Interpolated_Annual';

% Sheet 3: Linearly interpolated dataset (141 points, Table 5)
sheet141         = 'Interpolated_141points';

fprintf('\n=== ANN Modeling of PISA Scores (Turkey) ===\n');

%% -----------------------------------------------------------------------
%  2) Load datasets from Excel
% ------------------------------------------------------------------------
fprintf('\n[Data] Loading datasets from %s ...\n', dataFile);

% 2.1) Original PISA cycles (real observations only)
Orig = readmatrix(dataFile, 'Sheet', sheetOriginal);      % numeric part
% Columns assumed: [year, x1..x9, y1_math, y2_science, y3_reading]
years_real = Orig(:,1);
X_real     = Orig(:,2:10);    % 9 inputs
Y_real     = Orig(:,11:13);   % 3 outputs (Math, Science, Reading)

% 2.2) Annual interpolated dataset 2009–2023 (Table 4)
Ann  = readmatrix(dataFile, 'Sheet', sheetAnnual);
years_annual = Ann(:,1);
X_annual     = Ann(:,2:10);
Y_annual     = Ann(:,11:13);

% 2.3) High-resolution interpolated dataset (141 points, Table 5)
A141 = readmatrix(dataFile, 'Sheet', sheet141);
t_141  = A141(:,1);           % interpolated time grid (e.g., 2009, 2009.1, ...)
X_141  = A141(:,2:10);        % 9 inputs
Y_141  = A141(:,11:13);       % 3 outputs

fprintf('[Data] Loaded:\n');
fprintf('  - Original PISA cycles (real data):     %d rows\n', size(Orig,1));
fprintf('  - Annual interpolated data (2009–2023): %d rows\n', size(Ann,1));
fprintf('  - High-resolution interpolated data:    %d rows\n', size(A141,1));

%% -----------------------------------------------------------------------
%  3) Basic min–max summary (for documentation only, no normalization here)
% ------------------------------------------------------------------------
fprintf('\n[Data] Computing basic min–max summaries for inputs/outputs ...\n');

allData = [X_141 Y_141];
minVals = min(allData, [], 1);
maxVals = max(allData, [], 1);

fprintf('  Inputs (x1..x9) and outputs (y1..y3) min values:\n');
disp(minVals);
fprintf('  Inputs (x1..x9) and outputs (y1..y3) max values:\n');
disp(maxVals);

%% -----------------------------------------------------------------------
%  4) ANN model: tansig hidden layer (using 141-point dataset)
% ------------------------------------------------------------------------
fprintf('\n[ANN (Randomized trial results)] Training network with tansig hidden layer ...\n');

Input  = X_141;     % 141 × 9
Output = Y_141;     % 141 × 3

inputs  = Input';
targets = Output';

% Create feedforward network: 1 hidden layer, 9 neurons
net = fitnet(9, 'trainlm');

% Activation functions
net.layers{1}.transferFcn = 'tansig';   % hidden
net.layers{2}.transferFcn = 'purelin';  % output (default)

% Disable internal preprocessing (we work in original scale)
net.input.processFcns  = {};
net.output.processFcns = {};

% Data division: 70% train, 15% val, 15% test
net.divideFcn = 'dividerand';
net.divideMode = 'sample';
net.divideParam.trainRatio = 0.70;
net.divideParam.valRatio   = 0.15;
net.divideParam.testRatio  = 0.15;

% Performance function and training parameters
net.performFcn          = 'mse';
net.plotFcns            = {'plotperform','plottrainstate','ploterrhist','plotregression', 'plotfit'};
net.trainParam.epochs   = 1000;
net.trainParam.min_grad = 0;
net.trainParam.goal     = 1e-16;
net.trainParam.mu       = 1e-3;
net.trainParam.mu_max   = 1e100;
net.trainParam.max_fail = 1111111;

% Train network
[net,tr] = train(net, inputs, targets);

% <<weights and biases
b1 = net.b{1};
b2 = net.b{2};
IW = net.IW{1,1};
LW = net.LW{2,1};
% Display network parameters
fprintf('--- Network Parameters (Randomized trial) ---\n');

disp('b1 (Bias of hidden layer):');
disp(b1);

disp('b2 (Bias of output layer):');
disp(b2);

disp('IW (Input weights):');
disp(IW);

disp('LW (Layer weights):');
disp(LW);

fprintf('\n[ANN (Randomized trial results)] Final activation equation:\n');
fprintf('  y(x) = b2 + LW * tanh( b1 + IW * x )\n');
fprintf('  Size(IW) = %dx%d, Size(LW) = %dx%d\n', size(IW,1), size(IW,2), size(LW,1), size(LW,2));

%% -----------------------------------------------------------------------
%  5) ANN predictions on different datasets
% ------------------------------------------------------------------------
fprintf('\n[ANN (Randomized trial results)] Generating predictions on 141-point dataset ...\n');
Yhat_141 = net(inputs)';      % 141 × 3



% Helper for R²
compute_R2 = @(y, yhat) 1 - sum((y(:)-yhat(:)).^2)/sum((y(:)-mean(y(:))).^2);

%% 5.1) ANN performance for real PISA cycles only (Table 4 years)
fprintf('\n[ANN (Randomized trial results)] Performance evaluated at real PISA cycles only (2009, 2012, 2015, 2018, 2022) ...\n');

pisa_years = [2009; 2012; 2015; 2018; 2022];

% Get indices in annual dataset corresponding to those years
[tfPISA, idxPISA] = ismember(pisa_years, years_annual);
if any(~tfPISA)
    error('Some PISA years not found in annual dataset.');
end

X_pisa = X_annual(idxPISA,:);      % inputs at PISA years
Y_pisa = Y_annual(idxPISA,:);      % true outputs at PISA years

% ANN predictions at PISA years
Yhat_pisa = net(X_pisa')';
% Metrics per output
metrics_ANN_PISA = struct();
labels = {'Math','Science','Reading'};

for j = 1:3
    y_true = Y_pisa(:,j);
    y_hat  = Yhat_pisa(:,j);

    rmse_j = sqrt(mean((y_true - y_hat).^2));
    sse_j  = sum((y_true - y_hat).^2);
    R2_j   = compute_R2(y_true, y_hat);

    metrics_ANN_PISA(j).name = labels{j};
    metrics_ANN_PISA(j).RMSE = rmse_j;
    metrics_ANN_PISA(j).SSE  = sse_j;
    metrics_ANN_PISA(j).R2   = R2_j;

    fprintf('  ANN (Randomized trial results) (PISA years) – %s: RMSE = %.4f | SSE = %.4f | R² = %.4f\n', ...
        labels{j}, rmse_j, sse_j, R2_j);
end

%% 5.2) ANN performance for all annual data 2009–2023
fprintf('\n[ANN (Randomized trial results)] Performance evaluated on all annual data (2009–2023) 15 points\n');

Yhat_annual = net(X_annual')';

metrics_ANN_Annual = struct();
for j = 1:3
    y_true = Y_annual(:,j);
    y_hat  = Yhat_annual(:,j);

    rmse_j = sqrt(mean((y_true - y_hat).^2));
    sse_j  = sum((y_true - y_hat).^2);
    R2_j   = compute_R2(y_true, y_hat);

    metrics_ANN_Annual(j).name = labels{j};
    metrics_ANN_Annual(j).RMSE = rmse_j;
    metrics_ANN_Annual(j).SSE  = sse_j;
    metrics_ANN_Annual(j).R2   = R2_j;

    fprintf('  ANN (Randomized trial results) (Annual years(2009–2023)) – %s: RMSE = %.4f | SSE = %.4f | R² = %.4f\n', ...
        labels{j}, rmse_j, sse_j, R2_j);
end

%% =======================================================
% IN MANUSCRIPT coefficients
% =======================================================
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
IW_old = [
-1.0830785558671752	1.0017657438508758	2.608226477921692	-3.151806349373269	-4.047582852763107	2.0770248285525286	-2.671157678096608	5.893915380840322	0.745879413945609
5.566205608871914	-2.110533960119194	-2.6310330744956034	4.2036545522287065	3.330944443859584	-0.6303166751125107	-11.752966582827398	24.794883677019495	-5.184286106244985
3.1450245468193145	-0.08429764761946525	12.65736306950147	18.435933616213113	15.190391071082322	-18.944055084570888	-27.78777075924445	9.273377555142995	-2.434719242808797
-2.11629766023906	1.1545899793303818	1.0971319141997744	1.8784450601876086	-0.5102751629154296	2.0116185799168083	-2.211570733510068	0.8221831796602039	-0.6219384224895179
0.1650120792872276	-0.12511515773006085	0.0690418663188494	0.040058577788815095	0.02321009258707521	-0.26690444916739375	-0.1231010586883211	0.04956485031757055	0.06626010181019917
11.326035945807075	1.931410220208615	-3.1550689896586834	17.287589394150665	9.591437072535753	-10.61146080134936	2.1364933317450934	5.04732569103057	-19.738097744129046
3.9552685952750983	-6.452724460263063	2.4116217734142746	-16.474686689844326	21.748916908158243	21.5921277922777	-25.19975312053589	-11.957059703884557	0.48937567631116397
-0.06491763790267126	0.10513151420917145	-0.07325951856435581	-0.12206985331110988	-0.02589964916986947	0.27733717232182453	0.2661584930877467	-0.11599249344696526	-0.05734131016049306
6.820900502277753	-10.553177554297873	8.993053763766836	-5.824620859206694	0.22303996462418463	5.257418489235858	-9.316572710307783	2.484212037074705	13.700650054042033
];

LW_old = [
100.59050269727676	4.2150197327066055	-80.28845175614211	15.247334349186232	21.152221521505577	-93.86699396755962	32.74597290463664	33.99521502433319	33.12511867802862
101.00600580649672	1.0538351050088914	-123.0793839500205	26.12633479150988	42.90760594954905	-64.30795185204693	61.93359262550413	48.38426427638656	-10.283357962413525
105.72624991151997	9.618742519111018	-97.86831712380406	22.46313256268773	52.683098660484795	-92.16952323806314	29.38786249161064	59.26827830304763	-9.184004027680905
];

b1_old = [
6.885039377139719
10.87450578894299
-10.67473232537507
-19.228333506473472
4.8776688535813335
-3.8386818097587625
8.80762270305567
-7.760367834982238
-0.7116275605602532
];

b2_old = [
88.09463604402679
104.2701494722471
118.25606701448318
];
%% =======================================================================
% OPTIONAL: Compare with ANN coefficients in Manuscript
% =======================================================================

fprintf('\n==============================================================\n');
fprintf('ANN coefficients in manuscript:\n');
fprintf('These correspond to a network with tansig activation.\n');
fprintf('==============================================================\n\n');

answer = input('\nWould you like to evaluate performance using the coefficients presented in the manuscript (b1, b2, IW and LW)? (yes/no): ','s');
if strcmpi(answer,'yes')
    disp('--- IW_in_manuscript (9x9) ---'); disp(IW_old);
    disp('--- LW_in_manuscript (3x9) ---'); disp(LW_old);
    disp('--- b1_in_manuscript (9x1) ---'); disp(b1_old);
    disp('--- b2_in_manuscript (3x1) ---'); disp(b2_old);
    fprintf('\n[INFO] Evaluating IN MANUSCRIPT (weights presented in the manuscript) ...\n');
    % === Helper activation ===
    tansig_fn = @(x) 2./(1+exp(-2*x)) - 1;

    %% --------------------------------------------------------------
    % 1) PERFORMANCE ON REAL PISA CYCLES
    %% --------------------------------------------------------------
    fprintf('\n[IN MANUSCRIPT] Performance on REAL PISA cycles (2009, 2012, 2015, 2018, 2022)\n');

    H_pisa_old = tansig_fn( b1_old + IW_old * X_pisa.' );  
    Yhat_pisa_old = ( b2_old + LW_old * H_pisa_old ).';

    for j = 1:3
        y_true = Y_pisa(:,j);
        y_hat  = Yhat_pisa_old(:,j);

        rmse_j = sqrt(mean((y_true - y_hat).^2));
        sse_j  = sum((y_true - y_hat).^2);
        R2_j   = 1 - sum((y_true - y_hat).^2)/sum((y_true - mean(y_true)).^2);

        fprintf('  IN MANUSCRIPT (PISA years) – %s: RMSE=%.4f | SSE=%.4f | R²=%.4f\n', ...
            labels{j}, rmse_j, sse_j, R2_j);
    end

    %% --------------------------------------------------------------
    % 2) PERFORMANCE ON FULL 2009–2023 ANNUAL DATA (15 points)
    %% --------------------------------------------------------------
    fprintf('\n[IN MANUSCRIPT] Performance on FULL annual data (2009–2023) 15 points\n');

    H_annual_old = tansig_fn( b1_old + IW_old * X_annual.' );
    Yhat_annual_old = ( b2_old + LW_old * H_annual_old ).';

    for j = 1:3
        y_true = Y_annual(:,j);
        y_hat  = Yhat_annual_old(:,j);

        rmse_j = sqrt(mean((y_true - y_hat).^2));
        sse_j  = sum((y_true - y_hat).^2);
        R2_j   = 1 - sum((y_true - y_hat).^2)/sum((y_true - mean(y_true)).^2);

        fprintf('  IN MANUSCRIPT (All annual years) – %s: RMSE=%.4f | SSE=%.4f | R²=%.4f\n', ...
            labels{j}, rmse_j, sse_j, R2_j);
    end

    fprintf('\n[INFO] Comparison completed successfully.\n');

else
    fprintf('\n[INFO] Comparison with old coefficients skipped by user.\n');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% ============================================================
%  NEW TABLE: Real PISA vs ANN (Randomized) vs ANN (Manuscript)
% ============================================================

fprintf('\n[INFO] Building comparison table (2009–2023)...\n');

% ------------------------------------------------------------
% 1) REAL outputs (already in workspace: Y_annual)
% ------------------------------------------------------------
Y_real_math    = Y_annual(:,1);
Y_real_science = Y_annual(:,2);
Y_real_reading = Y_annual(:,3);

% ------------------------------------------------------------
% 2) RANDOMIZED network predictions
% ------------------------------------------------------------
Yhat_rand = net(X_annual')';   % 15×3

Y_rand_math    = Yhat_rand(:,1);
Y_rand_science = Yhat_rand(:,2);
Y_rand_reading = Yhat_rand(:,3);

% ------------------------------------------------------------
% 3) MANUSCRIPT COEFFICIENT PREDICTIONS
% ------------------------------------------------------------
tansig_fn = @(x) 2./(1+exp(-2*x)) - 1;

H_manuscript = tansig_fn( b1_old + IW_old * X_annual.' );  
Yhat_manuscript = ( b2_old + LW_old * H_manuscript ).';

Y_man_math    = Yhat_manuscript(:,1);
Y_man_science = Yhat_manuscript(:,2);
Y_man_reading = Yhat_manuscript(:,3);

% ------------------------------------------------------------
% 4) Build final table
% ------------------------------------------------------------
T = table( years_annual, ...
           Y_real_math, Y_real_science, Y_real_reading, ...
           Y_rand_math, Y_rand_science, Y_rand_reading, ...
           Y_man_math, Y_man_science, Y_man_reading );

T.Properties.VariableNames = { ...
    'Year', ...
    'Real_Math', 'Real_Science', 'Real_Reading', ...
    'Rand_Math', 'Rand_Science', 'Rand_Reading', ...
    'Manuscript_Math', 'Manuscript_Science', 'Manuscript_Reading' };

disp(' ');
disp('==================== COMPARISON TABLE (2009–2023) ====================');
disp(T);
disp('=======================================================================');





