Warrior_EA/AI/NeuronOCLConvPool.mqh

734 lines
33 KiB
MQL5
Raw Permalink Normal View History

refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
//+------------------------------------------------------------------+
//| NeuronOCLConvPool.mqh |
//| AnimateDread |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//| CNeuronConvOCL/CNeuronPoolOCL - the GPU-accelerated (OpenCL + |
//| DirectML) convolution and max-pooling layers. Both derive from |
//| CNeuronBaseOCL (AI\Network.mqh, must already be declared) and use|
//| CBufferDouble (AI\BufferDouble.mqh). Included from Network.mqh at|
//| the exact point these classes used to sit (right after |
//| CNeuronBaseOCL's own declaration, before CNeuronLSTMOCL), so |
//| ordering matches the original file. Extracted verbatim (SOLID |
//| cleanup) - no logic changes. |
//+------------------------------------------------------------------+
#include "BufferDouble.mqh"
//| GPU-accelerated convolution layer (OpenCL + DirectML). Ported |
//| from the NeuroNet_DNG reference library's CNeuronConvOCL/ |
//| CNeuronProofOCL, adapted to this project's double-precision |
//| CBufferDouble/COpenCLMy/CDirectMLMy conventions. A single |
//| (window+1)*window_out weight block is shared across every |
//| sliding position - unlike CNeuronBaseOCL, where every output has |
//| its own private weight vector. |
//+------------------------------------------------------------------+
class CNeuronConvOCL : public CNeuronBaseOCL
{
protected:
uint iWindow;
uint iStep;
uint iWindowOut;
CBufferDouble *WeightsConv;
CBufferDouble *DeltaWeightsConv;
CBufferDouble *FirstMomentumConv;
CBufferDouble *SecondMomentumConv;
//---
virtual bool feedForward(CNeuronBaseOCL *NeuronOCL);
virtual bool feedForwardCPU(CNeuronBaseOCL *NeuronOCL); // pure-MQL5 mirror of FeedForwardConv
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL);
public:
CNeuronConvOCL(void) : iWindow(1), iStep(1), iWindowOut(1)
{
WeightsConv = NULL;
DeltaWeightsConv = NULL;
FirstMomentumConv = NULL;
SecondMomentumConv = NULL;
}
~CNeuronConvOCL(void);
virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window_in, uint step, uint window_out, uint units_count, ENUM_OPTIMIZATION optimization_type);
virtual bool Init(uint numOutputs, uint myIndex, CDirectMLMy *direct_ml, uint window_in, uint step, uint window_out, uint units_count, ENUM_OPTIMIZATION optimization_type);
virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL);
virtual bool Save(int const file_handle);
virtual bool Load(int const file_handle);
virtual int Type(void) const { return defNeuronConvOCL; }
feat(ai): real conv receptive field + the reference's channel pool CONV's convolution used window = step = one bar, which is a per-bar projection - a 1x1 conv with a temporal receptive field of ONE BAR. It never mixed information across time, so "convolutional" described the layer type and nothing about what it computed. Same finding that sank HYBRID's LSTM. Pooling was removed on 2026-07-29 for being misconfigured against the conv output's memory layout. That removal was right; leaving the conv at a one-bar window was not. The two belong together: the NeuroNet_DNG reference (references\MQL5\Experts\EDL\Trajectory.mqh layers 2-5, kernels byte-identical to ours) pairs conv(window=2, step=1, window_out=4) with pool(window=4, step=4), and the pool only earns its place because a conv with a real receptive field sits above it. The input is bar-major (BufferTempData appends m_neuronsCount contiguous features per bar), so a flat window of k*m_neuronsCount spans exactly k bars - the receptive field needed NO kernel change. The conv output is position-major, so window == step == window_out is a clean max-over-channels, which is what the reference does and what the existing pool kernels already implement correctly. New chain at H1 defaults (420 = 20 bars x 21): conv1 w=42 s=21 out=8 -> 19 pos x 8 = 152 pool w=8 s=8 -> 19 conv2 w=2 s=1 out=8 -> 18 pos x 8 = 144 (effective field: 3 bars) We deliberately stop before the reference's SECOND pool: a channel pool emits one scalar per position, so a trailing pool would hand the dense stack 18 values and force it to fan out 18 -> 64. That is a bottleneck below every learnable layer - the same class of mistake the 2026-07-29 removal was about. Fixes a latent sizing bug this exposed: CNet's conv/pool position cursor tracked sliding POSITIONS, but a conv's real width is units_count * window_out. Any pool stacked on a conv would therefore have sized against a width window_out times too small and silently built the wrong shape. Both branches now read the built layer's actual Neurons(), which is what the batch-norm branch already did for the same reason. Also closes the architecture-pinning trap: a .nnw persists the window each conv was built with, so an existing CONV/HYBRID model would have loaded cleanly and gone on training under the OLD architecture. The conv weight tensor is (window+1)*window_out, so this cannot be repaired in place - EnforceTopologyContract now detects it, reports both shapes, and retrains. Conv chain shape is derived in one place (ConvReceptiveFieldBars / ConvFirstStagePositions / HasSecondConvStage / ConvOutputPositions / ConvOutputWidth) and consumed by AddConvStage, LstmFanIn and the startup config line, so what is built and what is logged cannot drift. Both builds compile 0 errors, 0 warnings. Forces a CONV and HYBRID retrain. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:05:37 -04:00
// Shape accessors. A .nnw persists the window/step it was BUILT with, so a model saved by an older
// build keeps that shape forever on load - these let EnforceTopologyContract() detect a stale
// receptive field instead of training on silently. See AI\Network.mqh's CNet::FirstConvWindow.
uint Window(void) const { return iWindow; }
uint Step(void) const { return iStep; }
uint WindowOut(void) const { return iWindowOut; }
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
// See CNeuronBaseOCL::getWeights/setWeights - same pair, targeting WeightsConv instead of the
// base class's Weights, for CNet::BlendWeightsFrom()'s EMA shadow-weight deployment.
virtual int getWeightsConv(double &values[]) { return (CheckPointer(WeightsConv) == POINTER_INVALID ? 0 : WeightsConv.GetData(values)); }
virtual bool setWeightsConv(double &values[])
{
if(CheckPointer(WeightsConv) == POINTER_INVALID)
return false;
if(!WeightsConv.AssignArray(values))
return false;
return WeightsConv.BufferWrite();
}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CNeuronConvOCL::~CNeuronConvOCL(void)
{
if(CheckPointer(WeightsConv) != POINTER_INVALID)
delete WeightsConv;
if(CheckPointer(DeltaWeightsConv) != POINTER_INVALID)
delete DeltaWeightsConv;
if(CheckPointer(FirstMomentumConv) != POINTER_INVALID)
delete FirstMomentumConv;
if(CheckPointer(SecondMomentumConv) != POINTER_INVALID)
delete SecondMomentumConv;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window_in, uint step, uint window_out, uint units_count, ENUM_OPTIMIZATION optimization_type)
{
if(window_out <= 0)
return false;
if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, units_count * window_out, optimization_type))
return false;
//---
iWindow = window_in;
iStep = step;
iWindowOut = (uint)fmax(window_out, 1);
//---
int count = (int)((iWindow + 1) * iWindowOut);
if(CheckPointer(WeightsConv) == POINTER_INVALID)
{
WeightsConv = new CBufferDouble();
if(CheckPointer(WeightsConv) == POINTER_INVALID)
return false;
}
if(!WeightsConv.Reserve(count))
return false;
// Fan-in-scaled (LeCun-uniform) init - see CNeuronBaseOCL::Init's OpenCL overload for the full
// rationale; fan-in here is the conv window size.
double weighScale = 1.0 / MathSqrt((double)iWindow + 1.0);
for(int i = 0; i < count; i++)
{
double weigh = ((MathRand() + 1) / 32768.0 - 0.5) * 2.0 * weighScale;
if(weigh == 0)
weigh = 0.001;
if(!WeightsConv.Add(weigh))
return false;
}
if(!WeightsConv.BufferCreate(OpenCL))
return false;
//---
if(optimization == SGD)
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID)
{
DeltaWeightsConv = new CBufferDouble();
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID)
return false;
}
if(!DeltaWeightsConv.BufferInit(count, 0))
return false;
if(!DeltaWeightsConv.BufferCreate(OpenCL))
return false;
}
else
{
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID)
{
FirstMomentumConv = new CBufferDouble();
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID)
return false;
}
if(!FirstMomentumConv.BufferInit(count, 0))
return false;
if(!FirstMomentumConv.BufferCreate(OpenCL))
return false;
//---
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID)
{
SecondMomentumConv = new CBufferDouble();
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID)
return false;
}
if(!SecondMomentumConv.BufferInit(count, 0))
return false;
if(!SecondMomentumConv.BufferCreate(OpenCL))
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| DirectML/D3D12 tier equivalent of Init(COpenCLMy*) above. |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::Init(uint numOutputs, uint myIndex, CDirectMLMy *direct_ml, uint window_in, uint step, uint window_out, uint units_count, ENUM_OPTIMIZATION optimization_type)
{
if(window_out <= 0)
return false;
if(!CNeuronBaseOCL::Init(numOutputs, myIndex, direct_ml, units_count * window_out, optimization_type))
return false;
//---
iWindow = window_in;
iStep = step;
iWindowOut = (uint)fmax(window_out, 1);
//---
int count = (int)((iWindow + 1) * iWindowOut);
if(CheckPointer(WeightsConv) == POINTER_INVALID)
{
WeightsConv = new CBufferDouble();
if(CheckPointer(WeightsConv) == POINTER_INVALID)
return false;
}
if(!WeightsConv.Reserve(count))
return false;
// Fan-in-scaled (LeCun-uniform) init - see the matching OpenCL Init() overload above.
double weighScale = 1.0 / MathSqrt((double)iWindow + 1.0);
for(int i = 0; i < count; i++)
{
double weigh = ((MathRand() + 1) / 32768.0 - 0.5) * 2.0 * weighScale;
if(weigh == 0)
weigh = 0.001;
if(!WeightsConv.Add(weigh))
return false;
}
if(!WeightsConv.BufferCreate(DirectML))
return false;
//---
if(optimization == SGD)
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID)
{
DeltaWeightsConv = new CBufferDouble();
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID)
return false;
}
if(!DeltaWeightsConv.BufferInit(count, 0))
return false;
if(!DeltaWeightsConv.BufferCreate(DirectML))
return false;
}
else
{
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID)
{
FirstMomentumConv = new CBufferDouble();
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID)
return false;
}
if(!FirstMomentumConv.BufferInit(count, 0))
return false;
if(!FirstMomentumConv.BufferCreate(DirectML))
return false;
//---
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID)
{
SecondMomentumConv = new CBufferDouble();
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID)
return false;
}
if(!SecondMomentumConv.BufferInit(count, 0))
return false;
if(!SecondMomentumConv.BufferCreate(DirectML))
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::feedForward(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID)
return false;
int positions = Output.Total() / (int)iWindowOut;
if(CheckPointer(DirectML) != POINTER_INVALID)
{
if(!DirectML.FeedForwardConv(WeightsConv.GetIndex(), NeuronOCL.getOutputIndex(), Output.GetIndex(),
NeuronOCL.Neurons(), (int)iStep, (int)iWindow, (int)iWindowOut, NativeActivationCode(activation), positions))
{
Print(__FUNCTION__ + ": " + DirectML.BackendName() + " FeedForwardConv failed, error " + IntegerToString(DirectML.LastError()));
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
return Output.BufferRead();
}
if(CheckPointer(OpenCL) == POINTER_INVALID)
return false;
uint global_work_offset[1] = {0};
uint global_work_size[1];
global_work_size[0] = (uint)positions;
OpenCL.SetArgumentBuffer(def_k_FeedForwardConv, def_k_ffc_matrix_w, WeightsConv.GetIndex());
OpenCL.SetArgumentBuffer(def_k_FeedForwardConv, def_k_ffc_matrix_i, NeuronOCL.getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_FeedForwardConv, def_k_ffc_matrix_o, Output.GetIndex());
OpenCL.SetArgument(def_k_FeedForwardConv, def_k_ffc_inputs, NeuronOCL.Neurons());
OpenCL.SetArgument(def_k_FeedForwardConv, def_k_ffc_step, (int)iStep);
OpenCL.SetArgument(def_k_FeedForwardConv, def_k_ffc_window_in, (int)iWindow);
OpenCL.SetArgument(def_k_FeedForwardConv, def_k_ffc_window_out, (int)iWindowOut);
OpenCL.SetArgument(def_k_FeedForwardConv, def_k_ffc_activation, NativeActivationCode(activation));
if(!OpenCL.Execute(def_k_FeedForwardConv, 1, global_work_offset, global_work_size))
{
printf("Error of execution kernel FeedForwardConv: %d", GetLastError());
return false;
}
//--- Output stays GPU-resident; see the note in CNeuronBaseOCL::feedForward().
return true;
}
//+------------------------------------------------------------------+
//| Pure-MQL5 double-precision mirror of Network.cl's FeedForwardConv |
//| kernel (host buffers only) - the CPU inference path. Filters live |
//| in this layer's own WeightsConv, [window_out][window_in+1] with |
//| the +1 bias last; inputs are the previous layer's Output. |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::feedForwardCPU(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID || CheckPointer(Output) == POINTER_INVALID || CheckPointer(WeightsConv) == POINTER_INVALID)
return false;
int inputs = NeuronOCL.Neurons();
int window_in = (int)iWindow;
int step = (int)iStep;
int window_out = (int)iWindowOut;
if(window_out <= 0)
return false;
int positions = Output.Total() / window_out;
int wTotal = WeightsConv.Total();
for(int i = 0; i < positions; i++)
{
int shift_out = window_out * i;
int shift_in = step * i;
for(int out = 0; out < window_out; out++)
{
int shift = (window_in + 1) * out;
if(shift + window_in >= wTotal)
return false;
int stop = (window_in <= (inputs - shift_in)) ? window_in : (inputs - shift_in);
double sum = 0.0;
for(int k = 0; k < stop; k++)
sum += NeuronOCL.OutputHost(shift_in + k) * WeightsConv.At(shift + k);
sum += WeightsConv.At(shift + window_in); // bias
switch(activation)
{
case TANH:
sum = tanh(sum);
break;
case SIGMOID:
sum = 1.0 / (1.0 + exp(-MathMax(-50.0, MathMin(50.0, sum))));
break;
case PRELU:
if(sum < 0.0)
sum *= 0.01;
break;
}
if(!Output.Update(out + shift_out, sum))
return false;
}
}
return true;
}
//+------------------------------------------------------------------+
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
//| Writes the gradient into NeuronOCL (the EARLIER/input-side layer) |
//| - opposite call direction from the dense calcHiddenGradients, but |
//| matches the reference library's own CNeuronConvOCL convention. |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID)
return false;
int outputs = Neurons();
if(CheckPointer(DirectML) != POINTER_INVALID)
{
if(!DirectML.CalcHiddenGradientConv(WeightsConv.GetIndex(), getGradientIndex(), NeuronOCL.getOutputIndex(), NeuronOCL.getGradientIndex(),
outputs, (int)iStep, (int)iWindow, (int)iWindowOut, (int)NeuronOCL.Activation(), NeuronOCL.Neurons()))
{
Print(__FUNCTION__ + ": " + DirectML.BackendName() + " CalcHiddenGradientConv failed, error " + IntegerToString(DirectML.LastError()));
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
double temp[];
return NeuronOCL.getGradient(temp) > 0;
}
if(CheckPointer(OpenCL) == POINTER_INVALID)
return false;
uint global_work_offset[1] = {0};
uint global_work_size[1];
global_work_size[0] = NeuronOCL.Neurons();
OpenCL.SetArgumentBuffer(def_k_CalcHiddenGradientConv, def_k_chgc_matrix_w, WeightsConv.GetIndex());
OpenCL.SetArgumentBuffer(def_k_CalcHiddenGradientConv, def_k_chgc_matrix_g, getGradientIndex());
OpenCL.SetArgumentBuffer(def_k_CalcHiddenGradientConv, def_k_chgc_matrix_o, NeuronOCL.getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_CalcHiddenGradientConv, def_k_chgc_matrix_ig, NeuronOCL.getGradientIndex());
OpenCL.SetArgument(def_k_CalcHiddenGradientConv, def_k_chgc_outputs, outputs);
OpenCL.SetArgument(def_k_CalcHiddenGradientConv, def_k_chgc_step, (int)iStep);
OpenCL.SetArgument(def_k_CalcHiddenGradientConv, def_k_chgc_window_in, (int)iWindow);
OpenCL.SetArgument(def_k_CalcHiddenGradientConv, def_k_chgc_window_out, (int)iWindowOut);
OpenCL.SetArgument(def_k_CalcHiddenGradientConv, def_k_chgc_activation, (int)NeuronOCL.Activation());
if(!OpenCL.Execute(def_k_CalcHiddenGradientConv, 1, global_work_offset, global_work_size))
{
printf("Error of execution kernel CalcHiddenGradientConv: %d", GetLastError());
return false;
}
//--- NeuronOCL's Gradient stays GPU-resident; its own calcHiddenGradients/calcInputGradients
//--- reads it via getGradientIndex(). The old getGradient(temp) call was a discarded-result
//--- sync (GetData() BufferRead()s internally) with no consumer of the read - pure overhead.
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::updateInputWeights(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID)
return false;
int inputs = NeuronOCL.Neurons();
if(CheckPointer(DirectML) != POINTER_INVALID)
{
if(optimization == SGD)
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
if(!DirectML.UpdateWeightsConvMomentum(WeightsConv.GetIndex(), getGradientIndex(), NeuronOCL.getOutputIndex(), DeltaWeightsConv.GetIndex(),
inputs, eta, alpha, (int)iWindow, (int)iWindowOut, (int)iStep, 0))
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
Print(__FUNCTION__ + ": " + DirectML.BackendName() + " UpdateWeightsConvMomentum failed, error " + IntegerToString(DirectML.LastError()));
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
}
else
{
double lt = eta * sqrt(1 - pow(b2, t)) / (1 - pow(b1, t));
if(!DirectML.UpdateWeightsConvAdam(WeightsConv.GetIndex(), getGradientIndex(), NeuronOCL.getOutputIndex(),
FirstMomentumConv.GetIndex(), SecondMomentumConv.GetIndex(), inputs, lt, b1, b2, (int)iWindow, (int)iWindowOut, (int)iStep))
{
Print(__FUNCTION__ + ": " + DirectML.BackendName() + " UpdateWeightsConvAdam failed, error " + IntegerToString(DirectML.LastError()));
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
t++;
}
//--- WeightsConv stays DLL-resident; feedForward reads it via GetIndex() (same as the OpenCL
//--- branch below). Save()/BlendWeightsFrom() BufferRead() on demand.
return true;
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
}
if(CheckPointer(OpenCL) == POINTER_INVALID)
return false;
uint global_work_offset[1] = {0};
uint global_work_size[1];
if(optimization == SGD)
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
global_work_size[0] = WeightsConv.Total();
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvMomentum, def_k_uwcm_matrix_w, WeightsConv.GetIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvMomentum, def_k_uwcm_matrix_g, getGradientIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvMomentum, def_k_uwcm_matrix_i, NeuronOCL.getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvMomentum, def_k_uwcm_matrix_dw, DeltaWeightsConv.GetIndex());
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_inputs, inputs);
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_learning_rates, (float)eta);
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_momentum, (float)alpha);
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_window_in, (int)iWindow);
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_window_out, (int)iWindowOut);
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_step, (int)iStep);
OpenCL.SetArgument(def_k_UpdateWeightsConvMomentum, def_k_uwcm_optimizer, 0);
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
ResetLastError();
if(!OpenCL.Execute(def_k_UpdateWeightsConvMomentum, 1, global_work_offset, global_work_size))
{
printf("Error of execution kernel UpdateWeightsConvMomentum: %d", GetLastError());
return false;
}
}
else
{
global_work_size[0] = iWindow + 1;
double lt = eta * sqrt(1 - pow(b2, t)) / (1 - pow(b1, t));
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvAdam, def_k_uwca_matrix_w, WeightsConv.GetIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvAdam, def_k_uwca_matrix_g, getGradientIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvAdam, def_k_uwca_matrix_i, NeuronOCL.getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvAdam, def_k_uwca_matrix_m, FirstMomentumConv.GetIndex());
OpenCL.SetArgumentBuffer(def_k_UpdateWeightsConvAdam, def_k_uwca_matrix_v, SecondMomentumConv.GetIndex());
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_inputs, inputs);
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_l, (float)lt);
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_b1, (float)b1);
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_b2, (float)b2);
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_window_in, (int)iWindow);
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_window_out, (int)iWindowOut);
OpenCL.SetArgument(def_k_UpdateWeightsConvAdam, def_k_uwca_step, (int)iStep);
ResetLastError();
if(!OpenCL.Execute(def_k_UpdateWeightsConvAdam, 1, global_work_offset, global_work_size))
{
printf("Error of execution kernel UpdateWeightsConvAdam: %d", GetLastError());
return false;
}
t++;
}
//--- WeightsConv stays GPU-resident; see the note in CNeuronBaseOCL::updateInputWeights().
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::Save(const int file_handle)
{
if(!CNeuronBaseOCL::Save(file_handle))
return false;
if(FileWriteInteger(file_handle, (int)iWindow, INT_VALUE) < INT_VALUE)
return false;
if(FileWriteInteger(file_handle, (int)iStep, INT_VALUE) < INT_VALUE)
return false;
if(FileWriteInteger(file_handle, (int)iWindowOut, INT_VALUE) < INT_VALUE)
return false;
if(CheckPointer(WeightsConv) == POINTER_INVALID || !WeightsConv.BufferRead() || !WeightsConv.Save(file_handle))
return false;
if(optimization == SGD)
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID || !DeltaWeightsConv.BufferRead() || !DeltaWeightsConv.Save(file_handle))
return false;
}
else
{
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID || !FirstMomentumConv.BufferRead() || !FirstMomentumConv.Save(file_handle))
return false;
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID || !SecondMomentumConv.BufferRead() || !SecondMomentumConv.Save(file_handle))
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronConvOCL::Load(const int file_handle)
{
if(!CNeuronBaseOCL::Load(file_handle))
return false;
iWindow = (uint)FileReadInteger(file_handle, INT_VALUE);
iStep = (uint)FileReadInteger(file_handle, INT_VALUE);
iWindowOut = (uint)FileReadInteger(file_handle, INT_VALUE);
//---
if(CheckPointer(WeightsConv) == POINTER_INVALID)
{
WeightsConv = new CBufferDouble();
if(CheckPointer(WeightsConv) == POINTER_INVALID)
return false;
}
if(WeightsConv.GetIndex() >= 0)
WeightsConv.BufferFree();
if(!WeightsConv.Load(file_handle))
return false;
if(!BackendBufferCreate(WeightsConv))
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
//---
if(optimization == SGD)
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
{
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID)
{
DeltaWeightsConv = new CBufferDouble();
if(CheckPointer(DeltaWeightsConv) == POINTER_INVALID)
return false;
}
if(DeltaWeightsConv.GetIndex() >= 0)
DeltaWeightsConv.BufferFree();
if(!DeltaWeightsConv.Load(file_handle))
return false;
if(!BackendBufferCreate(DeltaWeightsConv))
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
else
{
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID)
{
FirstMomentumConv = new CBufferDouble();
if(CheckPointer(FirstMomentumConv) == POINTER_INVALID)
return false;
}
if(FirstMomentumConv.GetIndex() >= 0)
FirstMomentumConv.BufferFree();
if(!FirstMomentumConv.Load(file_handle))
return false;
if(!BackendBufferCreate(FirstMomentumConv))
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
//---
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID)
{
SecondMomentumConv = new CBufferDouble();
if(CheckPointer(SecondMomentumConv) == POINTER_INVALID)
return false;
}
if(SecondMomentumConv.GetIndex() >= 0)
SecondMomentumConv.BufferFree();
if(!SecondMomentumConv.Load(file_handle))
return false;
if(!BackendBufferCreate(SecondMomentumConv))
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| GPU-accelerated max-pooling layer (OpenCL + DirectML). No weights,|
//| so no updateInputWeights work - just a sliding max. Ported from |
//| the NeuroNet_DNG reference's CNeuronProofOCL kernels. |
//+------------------------------------------------------------------+
class CNeuronPoolOCL : public CNeuronBaseOCL
{
protected:
uint iWindow;
uint iStep;
//---
virtual bool feedForward(CNeuronBaseOCL *NeuronOCL);
virtual bool feedForwardCPU(CNeuronBaseOCL *NeuronOCL); // pure-MQL5 mirror of FeedForwardProof
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) { return true; }
public:
CNeuronPoolOCL(void) : iWindow(2), iStep(1) {}
~CNeuronPoolOCL(void) {}
virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint step, uint units_count, ENUM_OPTIMIZATION optimization_type);
virtual bool Init(uint numOutputs, uint myIndex, CDirectMLMy *direct_ml, uint window, uint step, uint units_count, ENUM_OPTIMIZATION optimization_type);
virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL);
virtual bool Save(int const file_handle);
virtual bool Load(int const file_handle);
virtual int Type(void) const { return defNeuronPoolOCL; }
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint step, uint units_count, ENUM_OPTIMIZATION optimization_type)
{
if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, units_count, optimization_type))
return false;
iWindow = window;
iStep = step;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::Init(uint numOutputs, uint myIndex, CDirectMLMy *direct_ml, uint window, uint step, uint units_count, ENUM_OPTIMIZATION optimization_type)
{
if(!CNeuronBaseOCL::Init(numOutputs, myIndex, direct_ml, units_count, optimization_type))
return false;
iWindow = window;
iStep = step;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::feedForward(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID)
return false;
int outputs = Output.Total();
if(CheckPointer(DirectML) != POINTER_INVALID)
{
if(!DirectML.FeedForwardProof(NeuronOCL.getOutputIndex(), Output.GetIndex(), NeuronOCL.Neurons(), (int)iWindow, (int)iStep, outputs))
{
Print(__FUNCTION__ + ": " + DirectML.BackendName() + " FeedForwardProof failed, error " + IntegerToString(DirectML.LastError()));
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
return Output.BufferRead();
}
if(CheckPointer(OpenCL) == POINTER_INVALID)
return false;
uint offset1[1] = {0};
uint size1[1] = {(uint)outputs};
OpenCL.SetArgumentBuffer(def_k_FeedForwardProof, def_k_ffp_matrix_i, NeuronOCL.getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_FeedForwardProof, def_k_ffp_matrix_o, Output.GetIndex());
OpenCL.SetArgument(def_k_FeedForwardProof, def_k_ffp_inputs, NeuronOCL.Neurons());
OpenCL.SetArgument(def_k_FeedForwardProof, def_k_ffp_window, (int)iWindow);
OpenCL.SetArgument(def_k_FeedForwardProof, def_k_ffp_step, (int)iStep);
if(!OpenCL.Execute(def_k_FeedForwardProof, 1, offset1, size1))
{
printf("Error of execution kernel FeedForwardProof: %d", GetLastError());
return false;
}
//--- Output stays GPU-resident; see the note in CNeuronBaseOCL::feedForward().
return true;
}
//+------------------------------------------------------------------+
//| Pure-MQL5 mirror of Network.cl's FeedForwardProof kernel (sliding |
//| max-pool over the previous layer's Output). Host buffers only. |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::feedForwardCPU(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID || CheckPointer(Output) == POINTER_INVALID)
return false;
int outputs = Output.Total();
int inputs = NeuronOCL.Neurons();
int window = (int)iWindow;
int step = (int)iStep;
for(int i = 0; i < outputs; i++)
{
int pos = i * step;
if(pos >= inputs)
return false;
double result = NeuronOCL.OutputHost(pos);
for(int k = 1; k < window; k++)
{
int shift = k + pos;
if(shift >= inputs)
break;
result = MathMax(result, NeuronOCL.OutputHost(shift));
}
if(!Output.Update(i, result))
return false;
}
return true;
}
//+------------------------------------------------------------------+
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
//| Inverted-call convention, same as Conv/LSTM's calcInputGradients. |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
{
if(CheckPointer(NeuronOCL) == POINTER_INVALID)
return false;
int outputs = Neurons();
int inputs = NeuronOCL.Neurons();
if(CheckPointer(DirectML) != POINTER_INVALID)
{
if(!DirectML.CalcInputGradientProof(NeuronOCL.getOutputIndex(), getGradientIndex(), getOutputIndex(), NeuronOCL.getGradientIndex(),
outputs, (int)iWindow, (int)iStep, inputs))
{
Print(__FUNCTION__ + ": " + DirectML.BackendName() + " CalcInputGradientProof failed, error " + IntegerToString(DirectML.LastError()));
refactor(AI): split 8 self-contained classes out of the Network.mqh god-file AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation found method implementations for several classes (CNeuronBase/Pool/Conv, CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to split without risky manual reassembly. But 8 classes turned out to be genuinely self-contained (declaration + every method body physically contiguous, and only ever depended upon, never depending on anything declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer, CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL. Extracted each verbatim, via exact line-range extraction (not manual retyping) to eliminate transcription risk, into its own AI/*.mqh file, included from Network.mqh at the exact point each class used to sit - preserving original declaration order exactly. Mathematically verified byte-for-byte: reconstructing the original file from the 7 new files' bodies + Network.mqh's remaining segments is line-for-line identical to the pre-split git history. Compiled clean (MetaEditor, 0 errors/0 warnings) both before and after. The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv, CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base, CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) - splitting those safely needs deliberate per-method surgery, deferred to a future dedicated pass rather than rushed into this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00
return false;
}
double temp[];
return NeuronOCL.getGradient(temp) > 0;
}
if(CheckPointer(OpenCL) == POINTER_INVALID)
return false;
uint offset1[1] = {0};
uint size1[1] = {(uint)inputs};
OpenCL.SetArgumentBuffer(def_k_CalcInputGradientProof, def_k_cigp_matrix_i, NeuronOCL.getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_CalcInputGradientProof, def_k_cigp_matrix_g, getGradientIndex());
OpenCL.SetArgumentBuffer(def_k_CalcInputGradientProof, def_k_cigp_matrix_o, getOutputIndex());
OpenCL.SetArgumentBuffer(def_k_CalcInputGradientProof, def_k_cigp_matrix_ig, NeuronOCL.getGradientIndex());
OpenCL.SetArgument(def_k_CalcInputGradientProof, def_k_cigp_outputs, outputs);
OpenCL.SetArgument(def_k_CalcInputGradientProof, def_k_cigp_window, (int)iWindow);
OpenCL.SetArgument(def_k_CalcInputGradientProof, def_k_cigp_step, (int)iStep);
if(!OpenCL.Execute(def_k_CalcInputGradientProof, 1, offset1, size1))
{
printf("Error of execution kernel CalcInputGradientProof: %d", GetLastError());
return false;
}
//--- NeuronOCL's Gradient stays GPU-resident; see the note in
//--- CNeuronConvOCL::calcInputGradients().
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::Save(const int file_handle)
{
if(!CNeuronBaseOCL::Save(file_handle))
return false;
if(FileWriteInteger(file_handle, (int)iWindow, INT_VALUE) < INT_VALUE)
return false;
if(FileWriteInteger(file_handle, (int)iStep, INT_VALUE) < INT_VALUE)
return false;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CNeuronPoolOCL::Load(const int file_handle)
{
if(!CNeuronBaseOCL::Load(file_handle))
return false;
iWindow = (uint)FileReadInteger(file_handle, INT_VALUE);
iStep = (uint)FileReadInteger(file_handle, INT_VALUE);
return true;
}