2026-08-13 23:48:47 +03:00 | | | //+------------------------------------------------------------------+
|
| | | //| MyTreeNode.mqh |
|
| | | //| Copyright 2022, DNG |
|
| | | //| https://www.mql5.com/ru/users/dng |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2022, DNG"
|
| | | #property link "https://www.mql5.com/ru/users/dng"
|
| | | #property version "1.00"
|
| | | //---
|
| | | #include <Arrays\ArrayObj.mqh>
|
| | | //---
|
| | | class CMyTreeNode : public CArrayObj
|
| | | {
|
| | | protected:
|
| | | CMyTreeNode *m_cParent;
|
| | | ulong m_iIndex;
|
| | | float m_dSupport;
|
| | |
|
| | | public:
|
| | | CMyTreeNode();
|
| | | ~CMyTreeNode();
|
| | | //--- methods of access to protected data
|
| | | CMyTreeNode* Parent(void) const { return(m_cParent); }
|
| | | void Parent(CMyTreeNode *node) { m_cParent = node; }
|
| | | void IncreaseSupport(float support) { m_dSupport += support; }
|
| | | float GetSupport(void) { return m_dSupport; }
|
| | | void SetSupport(float support) { m_dSupport = support; }
|
| | | ulong ID(void) { return m_iIndex; }
|
| | | void ID(ulong ID) { m_iIndex = ID; }
|
| | | float GetConfidence(void);
|
| | | float GetConfidence(const ulong ID);
|
| | | //---
|
| | | CMyTreeNode *GetNext(const ulong ID);
|
| | | matrix NodesGetConfidence(void);
|
| | | CMyTreeNode *AddNode(const ulong ID, float weight = 0);
|
| | | bool DeleteNode(const ulong ID);
|
| | | //---
|
| | | uint GetDepth(void);
|
| | | //---
|
| | | bool Mining(vectorf &data, matrixf &paths, const ulong ID, float min_conf);
|
| | | //--- methods for working with files
|
| | | virtual bool Save(const int file_handle);
|
| | | virtual bool Load(const int file_handle);
|
| | | //--- method of creating an element of array
|
| | | virtual bool CreateElement(const int index);
|
| | | };
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| m d Su pp or t implementation |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | CMyTreeNode::CMyTreeNode() : m_dSupport(0)
|
2026-03-12 15:02:23 +02:00 | | | {
|
| | | Clear();
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | //| Destructor |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | CMyTreeNode::~CMyTreeNode()
|
2026-03-12 15:02:23 +02:00 | | | {
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | float CMyTreeNode::GetConfidence(void)
|
| | | {
|
| | | CMyTreeNode *parent = Parent();
|
| | | if(!parent)
|
| | | return 1;
|
| | | //---
|
| | | float result = m_dSupport / parent.GetSupport();
|
| | | return result;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | float CMyTreeNode::GetConfidence(const ulong ID)
|
| | | {
|
| | | CMyTreeNode *temp = GetNext(ID);
|
| | | if(!temp)
|
| | | return 0;
|
| | | //---
|
| | | return temp.GetConfidence();
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | //| Getting the element by ID |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | CMyTreeNode *CMyTreeNode::GetNext(const ulong ID)
|
2026-03-12 15:02:23 +02:00 | | | {
|
| | | if(m_data_total <= 0)
|
| | | return NULL;
|
| | | //---
|
| | | CMyTreeNode *result = NULL;
|
| | | for(int i = 0; i < m_data_total; i++)
|
| | | {
|
| | | CMyTreeNode *temp = m_data[i];
|
| | | if(!temp)
|
| | | continue;
|
| | | if(temp.ID() != ID)
|
| | | continue;
|
| | | result = temp;
|
| | | break;
|
| | | }
|
| | | //---
|
| | | return result;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | bool CMyTreeNode::DeleteNode(const ulong ID)
|
| | | {
|
| | | for(int i = 0; i < m_data_total; i++)
|
| | | {
|
| | | CMyTreeNode *temp = m_data[i];
|
| | | if(!temp)
|
| | | {
|
| | | if(!Delete(i))
|
| | | continue;
|
| | | return DeleteNode(ID);
|
| | | }
|
| | | if(temp.ID() != ID)
|
| | | continue;
|
| | | return Delete(i);
|
| | | }
|
| | | //---
|
| | | return false;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | //| Adding a node |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
2026-09-28 01:52:58 +03:00 | | | CMyTreeNode *CMyTreeNode::AddNode(const ulong ID, float support)
|
2026-03-12 15:02:23 +02:00 | | | {
|
| | | CMyTreeNode *node = new CMyTreeNode();
|
| | | if(!node)
|
| | | return node;
|
| | | node.ID(ID);
|
| | | if(!Add(node))
|
| | | {
|
| | | delete node;
|
| | | return node;
|
| | | }
|
| | | node.Parent(GetPointer(this));
|
| | | //---
|
| | | if(support > 0)
|
| | | node.SetSupport(support);
|
| | | return node;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | uint CMyTreeNode::GetDepth(void)
|
| | | {
|
| | | CMyTreeNode *parent = Parent();
|
| | | if(!parent)
|
| | | return 0;
|
| | | return parent.GetDepth() + 1;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | bool CMyTreeNode::Mining(vectorf &supports, matrixf &paths, const ulong ID, float min_conf)
|
| | | {
|
| | | if(ID == m_iIndex)
|
| | | if(GetConfidence() < min_conf)
|
| | | return true;
|
| | | //---
|
| | | float support = m_dSupport;
|
| | | for(int i = 0; i < m_data_total; i++)
|
| | | {
|
| | | CMyTreeNode *temp = m_data[i];
|
| | | if(!temp)
|
| | | {
|
| | | if(Delete(i))
|
| | | i--;
|
| | | continue;
|
| | | }
|
| | | if(!temp.Mining(supports, paths, (ID == m_iIndex ? ULONG_MAX : ID), min_conf))
|
| | | return false;
|
| | | support -= temp.GetSupport();
|
| | | if(temp.ID() == ID)
|
| | | if(Delete(i))
|
| | | i--;
|
| | | }
|
| | | //---
|
| | | if(ID == m_iIndex || ID == ULONG_MAX)
|
| | | if(support > 0 && !!m_cParent)
|
| | | {
|
| | | CMyTreeNode *parent = m_cParent;
|
| | | ulong row = paths.Rows();
|
| | | if(!paths.Resize(row + 1, paths.Cols()))
|
| | | return false;
|
| | | if(!paths.Row(vectorf::Zeros(paths.Cols()), row))
|
| | | return false;
|
| | | supports[m_iIndex] += support;
|
| | | while(!!parent)
|
| | | {
|
| | | if(parent.ID() != ULONG_MAX)
|
| | | {
|
| | | supports[parent.ID()] += support;
|
| | | paths[row, parent.ID()] = support;
|
| | | }
|
| | | parent = parent.Parent();
|
| | | }
|
| | | }
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | bool CMyTreeNode::CreateElement(const int index)
|
| | | {
|
| | | if(index >= m_data_max)
|
| | | if(!Resize(index + 1))
|
| | | return false;
|
| | | m_data[index] = new CMyTreeNode();
|
| | | if(!m_data[index])
|
| | | return false;
|
| | | m_data_total = fmax(index, m_data_total);
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | bool CMyTreeNode::Save(const int file_handle)
|
| | | {
|
| | | if(!CArrayObj::Save(file_handle))
|
| | | return false;
|
| | | if(FileWriteLong(file_handle, m_iIndex) < sizeof(m_iIndex))
|
| | | return false;
|
| | | if(FileWriteDouble(file_handle, m_dSupport) < sizeof(m_dSupport))
|
| | | return false;
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | | //| |
|
2026-03-12 15:02:23 +02:00 | | | //+------------------------------------------------------------------+
|
| | | bool CMyTreeNode::Load(const int file_handle)
|
| | | {
|
| | | if(!CArrayObj::Load(file_handle))
|
| | | return false;
|
| | | m_iIndex = FileReadLong(file_handle);
|
| | | m_dSupport = (float)FileReadDouble(file_handle);
|
| | | CMyTreeNode *point = GetPointer(this);
|
| | | //---
|
| | | for(int i = 0; i < m_data_total; i++)
|
| | | {
|
| | | CMyTreeNode *temp = m_data[i];
|
| | | if(!temp)
|
| | | {
|
| | | if(Delete(i))
|
| | | i--;
|
| | | continue;
|
| | | }
|
| | | temp.Parent(point);
|
| | | }
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | |
|