⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dstldlg.cpp

📁 自主式决策树学习的程序源码
💻 CPP
字号:
// dstlDlg.cpp : implementation file
//

#include "stdafx.h"
#include "dstl.h"
#include "dstlDlg.h"
#include "Tree.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDstlDlg dialog

CDstlDlg::CDstlDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDstlDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDstlDlg)
	m_TableName = _T("");
	m_ConditionNum = 0;
	m_RecNum = 0;
	m_leaveCount = 0;
	m_ClassNum = 0;
	m_ruleTable = _T("");
	m_testTable = _T("");
	m_ruleTable2 = _T("");
	m_cerTatio = _T("");
	m_nodeCount = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDstlDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDstlDlg)
	DDX_Text(pDX, IDC_EDITTableName, m_TableName);
	DDX_Text(pDX, IDC_EDITConditionNum, m_ConditionNum);
	DDX_Text(pDX, IDC_EDITRecNum, m_RecNum);
	DDX_Text(pDX, IDC_EDITleaveCount, m_leaveCount);
	DDX_Text(pDX, IDC_EDITClassNum, m_ClassNum);
	DDX_Text(pDX, IDC_EDITruleTable, m_ruleTable);
	DDX_Text(pDX, IDC_EDITtestTable, m_testTable);
	DDX_Text(pDX, IDC_EDITruleTable2, m_ruleTable2);
	DDX_Text(pDX, IDC_EDIT_cerRatio, m_cerTatio);
	DDX_Text(pDX, IDC_EDITnodeCount, m_nodeCount);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDstlDlg, CDialog)
	//{{AFX_MSG_MAP(CDstlDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BttnConnect, OnBttnConnect)
	ON_BN_CLICKED(IDC_BttnCreatTree, OnBttnCreatTree)
	ON_WM_PAINT()
	ON_BN_CLICKED(IDC_BttnTest, OnBttnTest)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDstlDlg message handlers

BOOL CDstlDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDstlDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDstlDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDstlDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}
//////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
//声明全局变量
CDatabase *pDb=new CDatabase;//CDatabase全局变量
int AttNumber=0;//条件属性个数
int ClassNumber=0;//决策类种类数
CString strTableName;//存放表名
CTree dtTree;//声明一棵决策数
int leaveCount=0;//叶结点个数
int nodeCount=0;//树结点总个数
CString strRuletable;//规则集表名
int recCount;//训练集记录数
CString strTestTable;//测试集

////////////////////////////////////////////////////////////////////
void CDstlDlg::OnBttnConnect() 
{
	// TODO: Add your control notification handler code here
	//连接数据源,统计并显示相关信息

    BOOL bStatus=false;//数据库是否成功打开标志
	//设置连接超时属性值为3秒钟
	pDb->SetLoginTimeout(3);
	try
	{
		bStatus=pDb->OpenEx(NULL);
		if(bStatus)
		{  TRACE("\n DB opened successfully");
		   //AfxMessageBox("数据源连接成功");
		}
		else
		{ 
			TRACE("\n open dsn failed\n");
		    AfxMessageBox("连接失败");
		}

	}
	catch(CMemoryException *pEx)//处理内存错误
	{
		pEx->ReportError();
	}
	catch(CDBException *pDBEx)//处理数据库异常
	{
		pDBEx->ReportError();
		TRACE("RetCode:%d strError:[%s] strStatus:[%s]\n",
			pDBEx->m_nRetCode,
			pDBEx->m_strError,
			pDBEx->m_strStateNativeOrigin);
	}
   
	CRecordset Rst(pDb);
	UpdateData(true);
	strTableName=m_TableName;
	CString strSQL="select * from "+strTableName;
	BOOL flag=false;
	flag=Rst.Open(CRecordset::dynaset,strSQL);
	strSQL="";//清空命令串
	if (flag)
		AfxMessageBox("数据表连接成功");
	AttNumber=Rst.GetODBCFieldCount()-2;//获得条件属性个数,(减掉ID,和决策属性)
	m_ConditionNum=AttNumber;//获得条件属性个数
	//获取记录条数
	m_RecNum=0;
	Rst.MoveFirst();
	while(!Rst.IsEOF())
	{
		m_RecNum++;
		Rst.MoveNext();
	}
    recCount=m_RecNum;
	Rst.Close();
	//获取决策属性个数
	CString strClassName;
	strClassName="ClassName";
	strSQL="select "+strClassName+" "
		+"from "+m_TableName+" "+"group by "+strClassName;
    Rst.Open(CRecordset::dynaset,strSQL);
	Rst.MoveFirst();
	m_ClassNum=0;
	while(!Rst.IsEOF())
	{
		m_ClassNum++;
		Rst.MoveNext();
	}
	ClassNumber=m_ClassNum;//赋值给全局变量ClassNumber
	UpdateData(false);
	
	Rst.Close();
	
	m_ruleTable="rule"+m_TableName;//默认规则集名称
	m_ruleTable2=m_ruleTable;//默认规则集名称
	UpdateData(false);
	//pDb->Close();
		
}

void CDstlDlg::OnBttnCreatTree() 
{
	// TODO: Add your control notification handler code here
	char * arrAtt=new char[AttNumber+1];//c++中char数组名解释为字符串的第一个字符的地址
	                                    //所以多分配1个单元用于存储字符串结束的空格
	for (int i=0;i<AttNumber;i++)//条件属性用“a,b,c........”表示
	{
		arrAtt[i]='a'+i;
	}

	TreeNode * bootNode=new (TreeNode);
    //初始化根结点
	dtTree.TreeBoot=bootNode;
    bootNode->AttArray=arrAtt;//当前条件属性
	bootNode->AttCount=AttNumber;//当前条件属性个数
	bootNode->strWh="";//用于确定当前记录集的where语句
	bootNode->ParNode=NULL;//根的父结点为空
	bootNode->SplitVal="";//根结点不是由某属性的某属性值得到的
    bootNode->ClassName="";//根结点不可能是叶结点
	bootNode->LeaveCer=0.0;//根结点不可能是叶结点
    bootNode->supRatio=0.0;//根结点不可能是叶结点
	
	strRuletable=m_ruleTable;//以下指令用于建立规则表用	
	UpdateData(true);
	CreatRuleTable(strRuletable);//建立规则表
	
	dtTree.CreatTree(bootNode);//建树并生成规则集
	
	m_leaveCount=leaveCount;
	
	UpdateData(false);
	AfxMessageBox("建树成功");
	
	//delete [] arrAtt;
	//aa.FreeList(AttList,AttNumber);
	//pDb->Close();
	int n=strTableName.GetLength()-5;//训练表名减掉train
	strTestTable=strTableName.Left(n)+"test";
	m_testTable=strTestTable;
	UpdateData(false);
	//释放空间
	dtTree.delTree(dtTree.TreeBoot);
	m_nodeCount=nodeCount;
	UpdateData(false);
}

////////////////////////////////////////////////////////////////////////////////
//建规则集表
void CDstlDlg::CreatRuleTable(CString strRuelTableName)
{
	CString strCmd;
	strCmd="create table "+strRuletable+" ( ";
    char mychar;
	for(int i=0;i<AttNumber;i++)//属性名即列名
	{
		mychar='a'+i;
		strCmd=strCmd+mychar+" varchar(255) , ";

	}
	strCmd=strCmd+"ClassName varchar(255),certainty varchar(255), support varchar(255))";
	pDb->ExecuteSQL(strCmd);
	
}


/////////////////////////////////////////////////////////////////////////////////
//测试
void CDstlDlg::OnBttnTest() 
{
	// TODO: Add your control notification handler code here
    //UpdateData(true);
	//int n=strTableName.GetLength()-5;//训练表名减掉train
	//CString strTestTable=strTableName.Left(n)+"test";
	//UpdateData(false);
	//CString strTestTable=m_testTable;//测试数据表名
	CRecordset rstRule(pDb);//规则数据集
	CRecordset rstTest(pDb);//测试数据集
	CString strSQLr;
	strSQLr="select * from "+strRuletable+" order by certainty desc,support desc";
	rstRule.Open(CRecordset::dynaset,strSQLr);
	int iCount=rstRule.GetODBCFieldCount()-3;//iCount-3表示减掉后面的决策属性、确定性和支持度
	
//用规则集的每一条规则去匹配测试集	
	
	rstRule.MoveFirst();//
	while(!rstRule.IsEOF())
	{
		CString strSQLwh=" where";
		
		for (int i=0;i<iCount;i++)
		{
			CString strValue;
			
			char ch='a'+i;
			rstRule.GetFieldValue(i,strValue);
			if(!strValue.IsEmpty())
			{
				
				strSQLwh=strSQLwh+" "+ch+"="+"'"+strValue+"'"+" and";
				strValue="";
			}
		}
		int iNum=strSQLwh.GetLength()-3;//去掉最后的and
		strSQLwh=strSQLwh.Left(iNum);
		
	    CString strC;
		rstRule.GetFieldValue("ClassName",strC);
		CString strSQL;
		strSQL="update "+strTestTable+" set tClass= "+"'"+strC+"'"
						+strSQLwh;
		//AfxMessageBox(strSQL);
		pDb->ExecuteSQL(strSQL);
		rstRule.MoveNext();
		
	}
    rstRule.Close();
	CRecordset rstTemp(pDb);//用于统计测试中正确的个数
	CString strSQLtemp;
	strSQLtemp="select count(*) as number from "+strTestTable+" where ClassName=tClass";
	rstTemp.Open(CRecordset::dynaset,strSQLtemp);
	CString strNumber;
	int index=0;
	rstTemp.GetFieldValue(index,strNumber);
	rstTemp.Close();
	strSQLtemp="";
	int cNumber;//正确个数
	sscanf(strNumber,"%d",&cNumber);
	strSQLtemp="select count(*) as number from "+strTestTable+" where ClassName is not null";
	rstTemp.Open(CRecordset::dynaset,strSQLtemp);
	rstTemp.GetFieldValue(index,strNumber);
	rstTemp.Close();
	int tNumber=0;//能匹配的总个数
	sscanf(strNumber,"%d",&tNumber);
	float fCer=(float)cNumber/tNumber;
	CString strCer;
	strCer.Format("%f",fCer);//计算确定性
	m_cerTatio=strCer;
	UpdateData(false);
	pDb->Close();//关闭数据源(库)
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -