[dasher] AlphabetManager subgroups populate themselves lazily, rather than use NF_SUBNODE
- From: Patrick Welche <pwelche src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [dasher] AlphabetManager subgroups populate themselves lazily, rather than use NF_SUBNODE
- Date: Sat, 19 Dec 2009 22:19:49 +0000 (UTC)
commit 63f418f6040d8c4926fa4fd30ab4964fb8e29386
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date: Tue Nov 24 10:58:34 2009 +0000
AlphabetManager subgroups populate themselves lazily, rather than use NF_SUBNODE
*Split CAlphNode into CSymbolNode and CGroupNode; latter stores state for lazy
*IterateChildGroups (once RecursiveIterateGroup but no longer recurses)
*combine code (mostly) common to GetRoot+RebuildParent into BuildNodeForOffset
*Fix rendering: outlines, "invisible" nodes, nodes filling parent copy colour
*Removed vSymbols vector from GetProbs etc. - was filled w/ vSymbols[i]==i !
*Added DasherNode::ExpectedNumChildren
*AlphIO counts & CAlphabet & SGroupInfo store no. of immediate child nodes
(characters/subgroups, inc space/paragraph/start&end conversion symbols)
*SCENode stores children in vector; ConversionHelper builds upon 1st request
Src/DasherCore/Alphabet/AlphIO.cpp | 8 +
Src/DasherCore/Alphabet/AlphIO.h | 1 +
Src/DasherCore/Alphabet/Alphabet.cpp | 2 +-
Src/DasherCore/Alphabet/Alphabet.h | 2 +-
Src/DasherCore/Alphabet/GroupInfo.h | 1 +
Src/DasherCore/AlphabetManager.cpp | 402 ++++++++++---------
Src/DasherCore/AlphabetManager.h | 115 ++++---
Src/DasherCore/ControlManager.cpp | 4 +-
Src/DasherCore/ControlManager.h | 1 +
Src/DasherCore/ConversionHelper.cpp | 166 ++-------
Src/DasherCore/ConversionHelper.h | 7 +-
Src/DasherCore/ConversionManager.cpp | 22 +-
Src/DasherCore/ConversionManager.h | 1 +
Src/DasherCore/DasherModel.cpp | 14 +-
Src/DasherCore/DasherNode.h | 5 +
Src/DasherCore/DasherViewSquare.cpp | 6 +-
.../LanguageModelling/PPMPYLanguageModel.cpp | 115 +++---
.../LanguageModelling/PPMPYLanguageModel.h | 2 +-
Src/DasherCore/MandarinAlphMgr.cpp | 17 +-
Src/DasherCore/MandarinAlphMgr.h | 8 +-
Src/DasherCore/NodeCreationManager.cpp | 9 +-
Src/DasherCore/NodeCreationManager.h | 2 +-
Src/DasherCore/PinYinConversionHelper.cpp | 44 +--
Src/DasherCore/PinYinConversionHelper.h | 4 +-
Src/DasherCore/PinyinParser.cpp | 14 +-
Src/DasherCore/SCENode.cpp | 31 +--
Src/DasherCore/SCENode.h | 23 +-
27 files changed, 442 insertions(+), 584 deletions(-)
---
diff --git a/Src/DasherCore/Alphabet/AlphIO.cpp b/Src/DasherCore/Alphabet/AlphIO.cpp
index 130f0c1..53072da 100644
--- a/Src/DasherCore/Alphabet/AlphIO.cpp
+++ b/Src/DasherCore/Alphabet/AlphIO.cpp
@@ -421,6 +421,7 @@ void CAlphIO::XML_StartElement(void *userData, const XML_Char *name, const XML_C
Me->InputInfo.EndConvertCharacter.Text = "";
Me->InputInfo.m_iCharacters = 1; // Start at 1 as 0 is the root node symbol
Me->InputInfo.m_pBaseGroup = 0;
+ Me->InputInfo.iNumChildNodes = 1; // the "root node" symbol (with text "")
Me->bFirstGroup = true;
Me->iGroupIdx = 0;
while(*atts != 0) {
@@ -552,8 +553,10 @@ void CAlphIO::XML_StartElement(void *userData, const XML_Char *name, const XML_C
if(strcmp(name, "group") == 0) {
SGroupInfo *pNewGroup(new SGroupInfo);
+ pNewGroup->iNumChildNodes=0;
pNewGroup->iColour = (Me->iGroupIdx % 3) + 110;
++Me->iGroupIdx;
+ if (Me->m_vGroups.empty()) Me->InputInfo.iNumChildNodes++; else Me->m_vGroups.back()->iNumChildNodes++;
if(Me->bFirstGroup) {
pNewGroup->bVisible = false;
@@ -696,6 +699,7 @@ void CAlphIO::XML_StartElement(void *userData, const XML_Char *name, const XML_C
AlphInfo::character NewCharacter;
++Me->InputInfo.m_iCharacters;
+ if (Me->m_vGroups.empty()) Me->InputInfo.iNumChildNodes++; else Me->m_vGroups.back()->iNumChildNodes++;
NewCharacter.Colour = -1;
@@ -751,6 +755,10 @@ void CAlphIO::XML_EndElement(void *userData, const XML_Char *name) {
if(strcmp(name, "alphabet") == 0) {
Reverse(Me->InputInfo.m_pBaseGroup);
+ if (Me->InputInfo.SpaceCharacter.Text != "") Me->InputInfo.iNumChildNodes++;
+ if (Me->InputInfo.ParagraphCharacter.Text != "") Me->InputInfo.iNumChildNodes++;
+ if (Me->InputInfo.StartConvertCharacter.Text != "") Me->InputInfo.iNumChildNodes++;
+ if (Me->InputInfo.EndConvertCharacter.Text != "") Me->InputInfo.iNumChildNodes++;
Me->Alphabets[Me->InputInfo.AlphID] = Me->InputInfo;
return;
}
diff --git a/Src/DasherCore/Alphabet/AlphIO.h b/Src/DasherCore/Alphabet/AlphIO.h
index e9ae602..2e90f96 100644
--- a/Src/DasherCore/Alphabet/AlphIO.h
+++ b/Src/DasherCore/Alphabet/AlphIO.h
@@ -76,6 +76,7 @@ public:
int m_iCharacters;
SGroupInfo *m_pBaseGroup;
+ int iNumChildNodes;
std::vector<character> m_vCharacters;
diff --git a/Src/DasherCore/Alphabet/Alphabet.cpp b/Src/DasherCore/Alphabet/Alphabet.cpp
index 875578e..2bfa11a 100644
--- a/Src/DasherCore/Alphabet/Alphabet.cpp
+++ b/Src/DasherCore/Alphabet/Alphabet.cpp
@@ -111,7 +111,7 @@ CAlphabet::CAlphabet(const CAlphIO::AlphInfo &AlphInfo)
// New group stuff
m_pBaseGroup = AlphInfo.m_pBaseGroup;
-
+ iNumChildNodes = AlphInfo.iNumChildNodes;
#ifdef DASHER_TRACE
Trace();
#endif
diff --git a/Src/DasherCore/Alphabet/Alphabet.h b/Src/DasherCore/Alphabet/Alphabet.h
index f2df2fc..6822019 100644
--- a/Src/DasherCore/Alphabet/Alphabet.h
+++ b/Src/DasherCore/Alphabet/Alphabet.h
@@ -135,7 +135,7 @@ namespace Dasher {
}
SGroupInfo *m_pBaseGroup;
-
+ int iNumChildNodes;
private:
// Add the characters that can appear in Nodes
diff --git a/Src/DasherCore/Alphabet/GroupInfo.h b/Src/DasherCore/Alphabet/GroupInfo.h
index 6f738a1..4ce1b3d 100644
--- a/Src/DasherCore/Alphabet/GroupInfo.h
+++ b/Src/DasherCore/Alphabet/GroupInfo.h
@@ -12,6 +12,7 @@ struct SGroupInfo {
int iEnd;
int iColour;
bool bVisible;
+ int iNumChildNodes;
};
/// \}
diff --git a/Src/DasherCore/AlphabetManager.cpp b/Src/DasherCore/AlphabetManager.cpp
index a6c4303..e0e0bee 100644
--- a/Src/DasherCore/AlphabetManager.cpp
+++ b/Src/DasherCore/AlphabetManager.cpp
@@ -54,85 +54,106 @@ CAlphabetManager::CAlphabetManager(CDasherInterfaceBase *pInterface, CNodeCreati
}
CAlphabetManager::CAlphNode::CAlphNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDisplayInfo, CAlphabetManager *pMgr)
-: CDasherNode(pParent, iLbnd, iHbnd, pDisplayInfo), m_pMgr(pMgr) {
+: CDasherNode(pParent, iLbnd, iHbnd, pDisplayInfo), m_pMgr(pMgr), m_pProbInfo(NULL) {
};
-CAlphabetManager::CAlphNode *CAlphabetManager::makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDisplayInfo) {
- return new CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, this);
+CAlphabetManager::CSymbolNode::CSymbolNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDisplayInfo, CAlphabetManager *pMgr, symbol _iSymbol)
+: CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, pMgr), iSymbol(_iSymbol) {
+};
+
+CAlphabetManager::CGroupNode::CGroupNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDisplayInfo, CAlphabetManager *pMgr, SGroupInfo *pGroup)
+: CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, pMgr), m_pGroup(pGroup) {
+};
+
+CAlphabetManager::CSymbolNode *CAlphabetManager::makeSymbol(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDisplayInfo, symbol iSymbol) {
+ return new CSymbolNode(pParent, iLbnd, iHbnd, pDisplayInfo, this, iSymbol);
+}
+
+CAlphabetManager::CGroupNode *CAlphabetManager::makeGroup(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDisplayInfo, SGroupInfo *pGroup) {
+ return new CGroupNode(pParent, iLbnd, iHbnd, pDisplayInfo, this, pGroup);
}
CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset) {
- std::vector<symbol> vContextSymbols;
+ CAlphNode *pNewNode = BuildNodeForOffset(pParent, iLower, iUpper, bEnteredLast, max(-1,iOffset-1), 0);
- if(iOffset>0) {
- // TODO: Utility function for looking up symbolic context
- // also TODO: make the LM get the context, rather than force it to fix max context length as an int
- int iStart = max(0, iOffset - (m_pLanguageModel->GetContextLength() + 1));
+ pNewNode->SetFlag(NF_SEEN, true);
+
+ // if(m_bGameMode) {
+ // pNodeUserData->iGameOffset = -1;
+ pNewNode->SetFlag(NF_GAME, true);
+ // }
+
+ return pNewNode;
+}
- pParent->GetContext(m_pInterface, vContextSymbols, iStart, iOffset - iStart);
- //take one off offset: the children (leaf) nodes (symbols) should have the specified offset;
- //the containing groups therefore have offset 1 less.
- iOffset = iOffset - 1;
+CAlphabetManager::CAlphNode *CAlphabetManager::BuildNodeForOffset(CDasherNode *pParent, int iLower, int iUpper, bool bSym, int iNewOffset, int iNewPhase) {
+
+ std::vector<symbol> vContextSymbols;
+ // TODO: make the LM get the context, rather than force it to fix max context length as an int
+ int iStart = max(0, iNewOffset - m_pLanguageModel->GetContextLength());
+
+ if(pParent) {
+ pParent->GetContext(m_pInterface, vContextSymbols, iStart, iNewOffset+1 - iStart);
} else {
- iOffset = -1;
- std::string strContext = m_pNCManager->GetAlphabet()->GetDefaultContext();
+ std::string strContext = (iNewOffset == -1)
+ ? m_pNCManager->GetAlphabet()->GetDefaultContext()
+ : m_pInterface->GetContext(iStart, iNewOffset+1 - iStart);
m_pNCManager->GetAlphabet()->GetSymbols(vContextSymbols, strContext);
}
- CLanguageModel::Context iContext;
- int iSymbol;
- BuildContext(vContextSymbols, !bEnteredLast, iContext, iSymbol);
- int iColour = m_pNCManager->GetAlphabet()->GetColour(iSymbol, 0);
- // FIXME - Make this a CDasherComponent
-
- // Stuff which could in principle be done in the symbol node creation routine
CDasherNode::SDisplayInfo *pDisplayInfo = new CDasherNode::SDisplayInfo;
- pDisplayInfo->iColour = iColour;
pDisplayInfo->bShove = true;
- pDisplayInfo->bVisible = true;
- pDisplayInfo->strDisplayText = m_pNCManager->GetAlphabet()->GetDisplayText(iSymbol);
-
- CAlphNode *pNewNode = makeNode(pParent, iLower, iUpper, pDisplayInfo);
+ pDisplayInfo->bVisible = true;
+
+ CAlphNode *pNewNode;
+ CLanguageModel::Context iContext = m_pLanguageModel->CreateEmptyContext();
+
+ for(std::vector<symbol>::iterator it(vContextSymbols.begin()); it != vContextSymbols.end(); ++it)
+ if(*it != 0)
+ m_pLanguageModel->EnterSymbol(iContext, *it);
+
+ if((vContextSymbols.size() == 0) || !bSym) {
+ //this node can't be responsible for entering the last symbol if there wasn't one!
+ pDisplayInfo->strDisplayText = ""; //equivalent to do m_pNCManager->GetAlphabet()->GetDisplayText(0)
+ pDisplayInfo->iColour = m_pNCManager->GetAlphabet()->GetColour(0, iNewPhase);
+ pNewNode = makeGroup(pParent, iLower, iUpper, pDisplayInfo, NULL);
+ } else {
+ const symbol iSymbol(vContextSymbols[vContextSymbols.size() - 1]);
+ pDisplayInfo->strDisplayText = m_pNCManager->GetAlphabet()->GetDisplayText(iSymbol);
+ pDisplayInfo->iColour = m_pNCManager->GetAlphabet()->GetColour(iSymbol, iNewPhase);
+ pNewNode = makeSymbol(pParent, iLower, iUpper, pDisplayInfo, iSymbol);
+ }
- pNewNode->m_iOffset = iOffset;
- pNewNode->iPhase = 0;
- pNewNode->iSymbol = iSymbol;
+ pNewNode->m_iOffset = iNewOffset;
+ pNewNode->iPhase = iNewPhase;
pNewNode->iContext = iContext;
-
- pNewNode->SetFlag(NF_SEEN, true);
-
-
-
- // if(m_bGameMode) {
- // pNodeUserData->iGameOffset = -1;
- pNewNode->SetFlag(NF_GAME, true);
- // }
-
return pNewNode;
}
-bool CAlphabetManager::CAlphNode::GameSearchNode(string strTargetUtf8Char) {
- if (GetFlag(NF_SUBNODE)) {
- if (GameSearchChildren(strTargetUtf8Char)) {
- SetFlag(NF_GAME, true);
- return true;
- }
- } else if (m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol) == strTargetUtf8Char) {
+bool CAlphabetManager::CSymbolNode::GameSearchNode(string strTargetUtf8Char) {
+ if (m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol) == strTargetUtf8Char) {
SetFlag(NF_GAME, true);
return true;
}
return false;
}
+bool CAlphabetManager::CGroupNode::GameSearchNode(string strTargetUtf8Char) {
+ if (GameSearchChildren(strTargetUtf8Char)) {
+ SetFlag(NF_GAME, true);
+ return true;
+ }
+return false;
+}
CLanguageModel::Context CAlphabetManager::CAlphNode::CloneAlphContext(CLanguageModel *pLanguageModel) {
if (iContext) return pLanguageModel->CloneContext(iContext);
return CDasherNode::CloneAlphContext(pLanguageModel);
}
-void CAlphabetManager::CAlphNode::GetContext(CDasherInterfaceBase *pInterface, vector<symbol> &vContextSymbols, int iOffset, int iLength) {
- if (!GetFlag(NF_SEEN) && iOffset+iLength-1 == m_iOffset && iSymbol) {
+void CAlphabetManager::CSymbolNode::GetContext(CDasherInterfaceBase *pInterface, vector<symbol> &vContextSymbols, int iOffset, int iLength) {
+ if (!GetFlag(NF_SEEN) && iOffset+iLength-1 == m_iOffset) {
if (iLength > 1) Parent()->GetContext(pInterface, vContextSymbols, iOffset, iLength-1);
vContextSymbols.push_back(iSymbol);
} else {
@@ -140,37 +161,105 @@ void CAlphabetManager::CAlphNode::GetContext(CDasherInterfaceBase *pInterface, v
}
}
-symbol CAlphabetManager::CAlphNode::GetAlphSymbol() {
+symbol CAlphabetManager::CSymbolNode::GetAlphSymbol() {
return iSymbol;
}
-void CAlphabetManager::CAlphNode::PopulateChildren() {
- m_pMgr->PopulateChildrenWithSymbol( this, -2, 0 );
+void CAlphabetManager::CSymbolNode::PopulateChildren() {
+ m_pMgr->IterateChildGroups(this, NULL, NULL);
+}
+int CAlphabetManager::CAlphNode::ExpectedNumChildren() {
+ return m_pMgr->m_pNCManager->GetAlphabet()->iNumChildNodes;
+}
+
+std::vector<unsigned int> *CAlphabetManager::CAlphNode::GetProbInfo() {
+ if (!m_pProbInfo) {
+ m_pProbInfo = new std::vector<unsigned int>();
+ m_pMgr->m_pNCManager->GetProbs(iContext, *m_pProbInfo, m_pMgr->m_pNCManager->GetLongParameter(LP_NORMALIZATION));
+ // work out cumulative probs in place
+ for(unsigned int i = 1; i < m_pProbInfo->size(); i++) {
+ (*m_pProbInfo)[i] += (*m_pProbInfo)[i - 1];
+ }
+ }
+ return m_pProbInfo;
+}
+
+std::vector<unsigned int> *CAlphabetManager::CGroupNode::GetProbInfo() {
+ if (m_pGroup && Parent() && Parent()->mgrId() == 0) {
+ DASHER_ASSERT(Parent()->m_iOffset == m_iOffset);
+ return (static_cast<CAlphNode *>(Parent()))->GetProbInfo();
+ }
+ //nope, no usable parent. compute here...
+ return CAlphNode::GetProbInfo();
}
-CAlphabetManager::CAlphNode *CAlphabetManager::CreateGroupNode(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd) {
+void CAlphabetManager::CGroupNode::PopulateChildren() {
+ m_pMgr->IterateChildGroups(this, m_pGroup, NULL);
+ if (GetChildren().size()==1) {
+ CDasherNode *pChild = GetChildren()[0];
+ //single child, must therefore completely fill this node...
+ DASHER_ASSERT(pChild->Lbnd()==0 && pChild->Hbnd()==65536);
+ //in earlier versions of Dasher with subnodes, that child would have been created
+ // at the same time as this node, so this node would never be seen/rendered (as the
+ // child would cover it). However, lazily (as we do now) creating the child, will
+ // suddenly obscure this (parent) node, changing it's colour. Hence, avoid this by
+ // making the child look like the parent...(note that changing the parent, before the
+ // child is created, to look like the child will do, would more closely mirror the old
+ // behaviour, but we can't really do that!
+ CDasherNode::SDisplayInfo *pInfo = (CDasherNode::SDisplayInfo *)pChild->GetDisplayInfo();
+ //ick, note the cast to get rid of 'const'ness. TODO: do something about SDisplayInfo...!!
+ pInfo->bVisible=false;
+ pInfo->iColour = GetDisplayInfo()->iColour;
+ }
+}
+int CAlphabetManager::CGroupNode::ExpectedNumChildren() {
+ return (m_pGroup) ? m_pGroup->iNumChildNodes : CAlphNode::ExpectedNumChildren();
+}
+CAlphabetManager::CGroupNode *CAlphabetManager::CreateGroupNode(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd) {
// TODO: More sensible structure in group data to map directly to this
CDasherNode::SDisplayInfo *pDisplayInfo = new CDasherNode::SDisplayInfo;
- pDisplayInfo->iColour = pInfo->iColour;
+ pDisplayInfo->iColour = (pInfo->bVisible ? pInfo->iColour : pParent->GetDisplayInfo()->iColour);
pDisplayInfo->bShove = true;
pDisplayInfo->bVisible = pInfo->bVisible;
pDisplayInfo->strDisplayText = pInfo->strLabel;
- CAlphNode *pNewNode = makeNode(pParent, iLbnd, iHbnd, pDisplayInfo);
+ CGroupNode *pNewNode = makeGroup(pParent, iLbnd, iHbnd, pDisplayInfo, pInfo);
- pNewNode->SetFlag(NF_SUBNODE, true);
+ //pNewNode->SetFlag(NF_SUBNODE, true);
// When creating a group node...
pNewNode->m_iOffset = pParent->m_iOffset; // ...the offset is the same as the parent...
pNewNode->iPhase = pParent->iPhase;
- // TODO: Sort out symbol for groups
- pNewNode->iSymbol = 0; //...but the Symbol is just a 0.
pNewNode->iContext = m_pLanguageModel->CloneContext(pParent->iContext);
return pNewNode;
}
+CAlphabetManager::CGroupNode *CAlphabetManager::CGroupNode::RebuildGroup(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd) {
+ if (pInfo == m_pGroup) {
+ SetRange(iLbnd, iHbnd);
+ SetParent(pParent);
+ //offset doesn't increase for groups...
+ DASHER_ASSERT (m_iOffset == pParent->m_iOffset);
+ return this;
+ }
+ CGroupNode *pRet=m_pMgr->CreateGroupNode(pParent, pInfo, iLbnd, iHbnd);
+ if (pInfo->iStart <= m_pGroup->iStart && pInfo->iEnd >= m_pGroup->iEnd) {
+ //created group node should contain this one
+ m_pMgr->IterateChildGroups(pRet,pInfo,this);
+ }
+ return pRet;
+}
+
+CAlphabetManager::CGroupNode *CAlphabetManager::CSymbolNode::RebuildGroup(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd) {
+ CGroupNode *pRet=m_pMgr->CreateGroupNode(pParent, pInfo, iLbnd, iHbnd);
+ if (pInfo->iStart <= iSymbol && pInfo->iEnd > iSymbol) {
+ m_pMgr->IterateChildGroups(pRet, pInfo, this);
+ }
+ return pRet;
+}
+
CLanguageModel::Context CAlphabetManager::CreateSymbolContext(CAlphNode *pParent, symbol iSymbol)
{
CLanguageModel::Context iContext = m_pLanguageModel->CloneContext(pParent->iContext);
@@ -178,24 +267,16 @@ CLanguageModel::Context CAlphabetManager::CreateSymbolContext(CAlphNode *pParent
return iContext;
}
-CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd) {
CDasherNode *pNewNode = NULL;
//Does not invoke conversion node
// TODO: Better way of specifying alternate roots
- // TODO: Building with existing node
- if(iSymbol == iExistingSymbol) {
- pNewNode = pExistingChild;
- pNewNode->SetRange(iLbnd, iHbnd);
- pNewNode->SetParent(pParent);
- DASHER_ASSERT(pExistingChild->m_iOffset == pParent->m_iOffset + 1);
-
- }
- // TODO: Need to fix fact that this is created even when control mode is switched off
- else if(iSymbol == m_pNCManager->GetAlphabet()->GetControlSymbol()) {
+ // TODO: Need to fix fact that this is created even when control mode is switched off
+ if(iSymbol == m_pNCManager->GetAlphabet()->GetControlSymbol()) {
//ACL setting offset as one more than parent for consistency with "proper" symbol nodes...
pNewNode = m_pNCManager->GetCtrlRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset+1);
@@ -227,7 +308,7 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymb
pDisplayInfo->strDisplayText = m_pNCManager->GetAlphabet()->GetDisplayText(iSymbol);
CAlphNode *pAlphNode;
- pNewNode = pAlphNode = makeNode(pParent, iLbnd, iHbnd, pDisplayInfo);
+ pNewNode = pAlphNode = makeSymbol(pParent, iLbnd, iHbnd, pDisplayInfo,iSymbol);
// std::stringstream ssLabel;
@@ -240,7 +321,6 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymb
pNewNode->m_iOffset = pParent->m_iOffset + 1;
pAlphNode->iPhase = iPhase;
- pAlphNode->iSymbol = iSymbol;
pAlphNode->iContext = CreateSymbolContext(pParent, iSymbol);
}
@@ -248,15 +328,31 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymb
return pNewNode;
}
+CDasherNode *CAlphabetManager::CSymbolNode::RebuildSymbol(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd) {
+ if(iSymbol == this->iSymbol) {
+ SetRange(iLbnd, iHbnd);
+ SetParent(pParent);
+ DASHER_ASSERT(m_iOffset == pParent->m_iOffset + 1);
+ return this;
+ }
+ return m_pMgr->CreateSymbolNode(pParent, iSymbol, iLbnd, iHbnd);
+}
+
+CDasherNode *CAlphabetManager::CGroupNode::RebuildSymbol(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd) {
+ return m_pMgr->CreateSymbolNode(pParent, iSymbol, iLbnd, iHbnd);
+}
-void CAlphabetManager::RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+void CAlphabetManager::IterateChildGroups(CAlphNode *pParent, SGroupInfo *pParentGroup, CAlphNode *buildAround) {
+ std::vector<unsigned int> *pCProb(pParent->GetProbInfo());
+ const int iMin(pParentGroup ? pParentGroup->iStart : 1);
+ const int iMax(pParentGroup ? pParentGroup->iEnd : pCProb->size());
// TODO: Think through alphabet file formats etc. to make this class easier.
// TODO: Throw a warning if parent node already has children
// Create child nodes and add them
int i(iMin); //lowest index of child which we haven't yet added
- SGroupInfo *pCurrentNode(pInfo);
+ SGroupInfo *pCurrentNode(pParentGroup ? pParentGroup->pChild : m_pNCManager->GetAlphabet()->m_pBaseGroup);
// The SGroupInfo structure has something like linked list behaviour
// Each SGroupInfo contains a pNext, a pointer to a sibling group info
while (i < iMax) {
@@ -277,21 +373,10 @@ void CAlphabetManager::RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pIn
((*pCProb)[iMax-1] - (*pCProb)[iMin-1]);
if (bSymbol) {
- pNewChild = CreateSymbolNode(pParent, (*pSymbols)[i], iLbnd, iHbnd, iExistingSymbol, pExistingChild);
+ pNewChild = (buildAround) ? buildAround->RebuildSymbol(pParent, i, iLbnd, iHbnd) : CreateSymbolNode(pParent, i, iLbnd, iHbnd);
i++; //make one symbol at a time - move onto next in next iteration
} else { //in/reached subgroup - do entire group in one go:
- CAlphNode *pNew;
- pNewChild= pNew= CreateGroupNode(pParent,
- pCurrentNode, iLbnd, iHbnd);
-
- RecursiveIterateGroup(pNew,
- pCurrentNode->pChild,
- pSymbols,
- pCProb,
- pCurrentNode->iStart,
- pCurrentNode->iEnd,
- iExistingSymbol, pExistingChild);
-
+ pNewChild= (buildAround) ? buildAround->RebuildGroup(pParent, pCurrentNode, iLbnd, iHbnd) : CreateGroupNode(pParent, pCurrentNode, iLbnd, iHbnd);
i = pCurrentNode->iEnd; //make one group at a time - so move past entire group...
pCurrentNode = pCurrentNode->pNext;
}
@@ -301,119 +386,73 @@ void CAlphabetManager::RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pIn
pParent->SetFlag(NF_ALLCHILDREN, true);
}
-void CAlphabetManager::PopulateChildrenWithSymbol( CAlphNode *pNode, int iExistingSymbol, CDasherNode *pExistingChild ) {
- // TODO: generally improve with iterators etc.
- // FIXME: this has to change for history stuff and Japanese dasher
- std::vector < symbol > newchars; // place to put this list of characters
- std::vector < unsigned int >cum; // for the probability list
-
- // TODO: Need to fix up relation to language model here (use one from node, not global).
- m_pNCManager->GetProbs(pNode->iContext, newchars, cum, m_pNCManager->GetLongParameter(LP_NORMALIZATION));
- int iChildCount = newchars.size();
-
- // work out cumulative probs in place
- for(int i = 1; i < iChildCount; i++) {
- cum[i] += cum[i - 1];
- }
-
- RecursiveIterateGroup(pNode, m_pNCManager->GetAlphabet()->m_pBaseGroup, &newchars,
- &cum, 1, iChildCount, iExistingSymbol, pExistingChild);
-}
-
CAlphabetManager::CAlphNode::~CAlphNode() {
+ delete m_pProbInfo;
m_pMgr->m_pLanguageModel->ReleaseContext(iContext);
}
-void CAlphabetManager::CAlphNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization) {
+void CAlphabetManager::CSymbolNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization) {
//std::cout << this << " " << Parent() << ": Output at offset " << m_iOffset << " *" << m_pMgr->m_pNCManager->GetAlphabet()->GetText(t) << "* " << std::endl;
- if(iSymbol) { // Ignore symbol 0 (root node)
- Dasher::CEditEvent oEvent(1, m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol), m_iOffset);
- m_pMgr->m_pNCManager->InsertEvent(&oEvent);
+ Dasher::CEditEvent oEvent(1, m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol), m_iOffset);
+ m_pMgr->m_pNCManager->InsertEvent(&oEvent);
- // Track this symbol and its probability for logging purposes
- if (pAdded != NULL) {
- Dasher::SymbolProb sItem;
- sItem.sym = iSymbol;
- sItem.prob = GetProb(iNormalization);
+ // Track this symbol and its probability for logging purposes
+ if (pAdded != NULL) {
+ Dasher::SymbolProb sItem;
+ sItem.sym = iSymbol;
+ sItem.prob = GetProb(iNormalization);
- pAdded->push_back(sItem);
- }
+ pAdded->push_back(sItem);
}
}
-void CAlphabetManager::CAlphNode::Undo() {
- if(iSymbol) { // Ignore symbol 0 (root node)
- Dasher::CEditEvent oEvent(2, m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol), m_iOffset);
- m_pMgr->m_pNCManager->InsertEvent(&oEvent);
- }
+void CAlphabetManager::CSymbolNode::Undo() {
+ Dasher::CEditEvent oEvent(2, m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol), m_iOffset);
+ m_pMgr->m_pNCManager->InsertEvent(&oEvent);
}
-// TODO: Sort out node deletion etc.
-CDasherNode *CAlphabetManager::CAlphNode::RebuildParent() {
- int iNewOffset = m_iOffset - 1;
-
- int iOldPhase(iPhase);
- int iNewPhase;
-
- symbol iNewSymbol;
-
- std::vector<symbol> vContextSymbols;
- CLanguageModel::Context iContext;
+CDasherNode *CAlphabetManager::CGroupNode::RebuildParent() {
+ // CAlphNode's always have a parent, they inserted a symbol; CGroupNode's
+ // with an m_pGroup have a container i.e. the parent group, unless
+ // m_pGroup==NULL => "root" node where Alphabet->m_pBaseGroup is the *first*child*...
+ if (m_pGroup == NULL) return NULL;
+ //offset of group node is same as parent...
+ return CAlphNode::RebuildParent(m_iOffset, iPhase);
+}
- if((m_iOffset == -1) || (iSymbol == 0)) {
- // already a root, or for some other reason has the null
- // symbol (eg because it was generated from a different alphabet)
- return NULL;
- }
+CDasherNode *CAlphabetManager::CSymbolNode::RebuildParent() {
+ //parent's offset is one less than this.
+ return CAlphNode::RebuildParent(m_iOffset-1, (iPhase + 1)%2);
+}
- CDasherNode::SDisplayInfo *pDisplayInfo = new CDasherNode::SDisplayInfo;
- pDisplayInfo->bShove = true;
- pDisplayInfo->bVisible = true;
+CDasherNode *CAlphabetManager::CAlphNode::RebuildParent(int iNewOffset, int iNewPhase) {
+ //possible that we have a parent, as RebuildParent() rebuilds back to closest AlphNode.
+ if (Parent()) return Parent();
- if(m_iOffset == 0) {
- // TODO: Creating a root node, Shouldn't be a special case
- std::string strContext = m_pMgr->m_pNCManager->GetAlphabet()->GetDefaultContext();
- m_pMgr->m_pNCManager->GetAlphabet()->GetSymbols(vContextSymbols, strContext);
- m_pMgr->BuildContext(vContextSymbols, true, iContext, iNewSymbol); //sets iNewSymbol to 0
-
- iNewPhase = 0;
-
- pDisplayInfo->strDisplayText = "";
- }
- else {
- int iStart = max(0, m_iOffset - (m_pMgr->m_pLanguageModel->GetContextLength() + 1));
- GetContext(m_pMgr->m_pInterface, vContextSymbols, iStart, m_iOffset - iStart);
- m_pMgr->BuildContext(vContextSymbols, false, iContext, iNewSymbol);
-
- iNewPhase = ((iOldPhase + 2 - 1) % 2);
-
- pDisplayInfo->strDisplayText = m_pMgr->m_pNCManager->GetAlphabet()->GetDisplayText(iNewSymbol);
- }
- pDisplayInfo->iColour = m_pMgr->m_pNCManager->GetAlphabet()->GetColour(iNewSymbol, iNewPhase);
-
- CAlphNode *pNewNode = m_pMgr->makeNode(NULL, 0, 0, pDisplayInfo);
+ //Hmmm. We require that if the new node's offset is -1 (the very beginning), phase is 0.
+ // If you escaped from control mode back to alphabet with an odd offset, GetRoot (with odd DasherNode offset)
+ // would construct a root with phase 0; if you then wrote far enough forwards first to lose the Control Mode nodes,
+ // and then erased back far enough to delete the entire (pre-Control-Mode) sentence, might that break this? TODO CHECK
+ // (and TODO: possibly remove phase - why not just use iOffset modulo 2? (Or however many, could then decide according
+ // to colour scheme or whatever!)
+ DASHER_ASSERT(iNewOffset !=-1 || iNewPhase == 0);
- // TODO: Some of this context stuff could be consolidated
+ CAlphNode *pNewNode = m_pMgr->BuildNodeForOffset(NULL, 0, 0, iNewOffset!=-1, iNewOffset, iNewPhase);
pNewNode->SetFlag(NF_SEEN, true);
- pNewNode->m_iOffset = iNewOffset;
- pNewNode->iPhase = iNewPhase;
- pNewNode->iSymbol = iNewSymbol;
- pNewNode->iContext = iContext;
-
+ //now fill in the new node - recursively - until it reaches us
+ m_pMgr->IterateChildGroups(pNewNode, NULL, this);
- m_pMgr->PopulateChildrenWithSymbol(pNewNode, iSymbol, this);
-
- // std::cout << "**" << std::endl;
-
- return pNewNode;
+ //finally return our immediate parent (pNewNode may be an ancestor rather than immediate parent!)
+ DASHER_ASSERT(Parent() != NULL);
+ return Parent();
}
// TODO: Shouldn't there be an option whether or not to learn as we write?
// For want of a better solution, game mode exemption explicit in this function
-void CAlphabetManager::CAlphNode::SetFlag(int iFlag, bool bValue) {
+void CAlphabetManager::CSymbolNode::SetFlag(int iFlag, bool bValue) {
CDasherNode::SetFlag(iFlag, bValue);
switch(iFlag) {
case NF_COMMITTED:
@@ -422,20 +461,3 @@ void CAlphabetManager::CAlphNode::SetFlag(int iFlag, bool bValue) {
break;
}
}
-
-void CAlphabetManager::BuildContext(const std::vector<symbol> &vContextSymbols, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol) {
- // Hopefully this will obsolete any need to handle contexts outside
- // of the alphabet manager - check this and remove resulting
- // redundant code
-
- oContext = m_pLanguageModel->CreateEmptyContext();
-
- for(std::vector<symbol>::const_iterator it(vContextSymbols.begin()); it != vContextSymbols.end(); ++it)
- if(*it != 0)
- m_pLanguageModel->EnterSymbol(oContext, *it);
-
- if((vContextSymbols.size() == 0) || bRoot)
- iSymbol = 0;
- else
- iSymbol = vContextSymbols[vContextSymbols.size() - 1];
-}
diff --git a/Src/DasherCore/AlphabetManager.h b/Src/DasherCore/AlphabetManager.h
index a119f86..eef5774 100644
--- a/Src/DasherCore/AlphabetManager.h
+++ b/Src/DasherCore/AlphabetManager.h
@@ -31,7 +31,7 @@ struct SGroupInfo;
namespace Dasher {
class CDasherInterfaceBase;
-
+
/// \ingroup Model
/// @{
@@ -46,45 +46,69 @@ namespace Dasher {
CAlphabetManager(CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager, CLanguageModel *pLanguageModel);
protected:
+ class CGroupNode;
class CAlphNode : public CDasherNode {
public:
int mgrId() {return 0;}
CAlphNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr);
- ///
- /// Provide children for the supplied node
- ///
-
- virtual void PopulateChildren();
-
- ///
- /// Delete any storage alocated for this node
- ///
-
- virtual ~CAlphNode();
-
- virtual void Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization);
- virtual void Undo();
-
- virtual CDasherNode *RebuildParent();
-
- virtual void SetFlag(int iFlag, bool bValue);
-
- virtual bool GameSearchNode(std::string strTargetUtf8Char);
-
- virtual CLanguageModel::Context CloneAlphContext(CLanguageModel *pLanguageModel);
- virtual void GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength);
- virtual symbol GetAlphSymbol();
- private:
- CAlphabetManager *m_pMgr;
- public: //to AlphabetManager and subclasses only, of course...
-
- symbol iSymbol;
int iPhase;
CLanguageModel::Context iContext;
-
- int iGameOffset;
+ ///
+ /// Delete any storage alocated for this node
+ ///
+ virtual ~CAlphNode();
+ virtual CLanguageModel::Context CloneAlphContext(CLanguageModel *pLanguageModel);
+ CDasherNode *RebuildParent(int iNewOffset, int iNewPhase);
+ ///Have to call this from CAlphabetManager, and from CGroupNode on a _different_ CAlphNode, hence public...
+ virtual std::vector<unsigned int> *GetProbInfo();
+ virtual int ExpectedNumChildren();
+ CAlphabetManager *m_pMgr;
+ virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd)=0;
+ virtual CGroupNode *RebuildGroup(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd)=0;
+ private:
+ std::vector<unsigned int> *m_pProbInfo;
+ };
+ class CSymbolNode : public CAlphNode {
+ public:
+ CSymbolNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr, symbol iSymbol);
+
+ ///
+ /// Provide children for the supplied node
+ ///
+
+ virtual void PopulateChildren();
+ virtual CDasherNode *RebuildParent();
+ virtual void Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization);
+ virtual void Undo();
+
+ virtual void SetFlag(int iFlag, bool bValue);
+
+ virtual bool GameSearchNode(std::string strTargetUtf8Char);
+ virtual void GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength);
+ virtual symbol GetAlphSymbol();
+ const symbol iSymbol;
+ virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd);
+ virtual CGroupNode *RebuildGroup(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd);
};
+ class CGroupNode : public CAlphNode {
+ public:
+ CGroupNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr, SGroupInfo *pGroup);
+
+ ///
+ /// Provide children for the supplied node
+ ///
+ virtual CDasherNode *RebuildParent();
+ virtual void PopulateChildren();
+ virtual int ExpectedNumChildren();
+ virtual bool GameSearchNode(std::string strTargetUtf8Char);
+ virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd);
+ virtual CGroupNode *RebuildGroup(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd);
+ std::vector<unsigned int> *GetProbInfo();
+ private:
+ SGroupInfo *m_pGroup;
+ };
+
public:
///
/// Get a new root node owned by this manager
@@ -97,30 +121,33 @@ namespace Dasher {
///
/// Factory method for CAlphNode construction, so subclasses can override.
///
- virtual CAlphNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
-
+ virtual CSymbolNode *makeSymbol(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, symbol iSymbol);
+ virtual CGroupNode *makeGroup(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, SGroupInfo *pGroup);
- void PopulateChildrenWithSymbol( CAlphNode *pNode, int iExistingSymbol, CDasherNode *pExistingChild );
-
- virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild);
+ virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd);
virtual CLanguageModel::Context CreateSymbolContext(CAlphNode *pParent, symbol iSymbol);
+ virtual CGroupNode *CreateGroupNode(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd);
+ ///
+ ///Builds a new node from the context leading up to the specified offset
+ /// bSym - true if the build node should be considered as having entered the last symbol (e.g. when rebuilding parent,
+ /// but not when escaping back to Alphabet)
+ /// iNewOffset - m_iOffset of the new node (i.e. index into context of character the node represents)
+ ///
+ CAlphNode *BuildNodeForOffset(CDasherNode *pParent, int iLower, int iUpper, bool bSym, int iNewOffset, int iNewPhase);
+
CLanguageModel *m_pLanguageModel;
CNodeCreationManager *m_pNCManager;
private:
- void BuildContext(const std::vector<symbol> &vContextSymbols, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol);
-
- void RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild);
-
- CAlphNode *CreateGroupNode(CAlphNode *pParent, SGroupInfo *pInfo, unsigned int iLbnd, unsigned int iHbnd);
+ void IterateChildGroups(CAlphNode *pParent, SGroupInfo *pParentGroup, CAlphNode *buildAround);
CLanguageModel::Context m_iLearnContext;
CDasherInterfaceBase *m_pInterface;
-
+
};
- /// @}
+/// @}
}
diff --git a/Src/DasherCore/ControlManager.cpp b/Src/DasherCore/ControlManager.cpp
index 3b4d217..a118839 100644
--- a/Src/DasherCore/ControlManager.cpp
+++ b/Src/DasherCore/ControlManager.cpp
@@ -339,7 +339,9 @@ void CControlManager::CContNode::PopulateChildren() {
++iIdx;
}
}
-
+int CControlManager::CContNode::ExpectedNumChildren() {
+ return pControlItem->vChildren.size();
+}
void CControlManager::CContNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization ) {
CControlEvent oEvent(pControlItem->iID);
diff --git a/Src/DasherCore/ControlManager.h b/Src/DasherCore/ControlManager.h
index 560d2e4..7136485 100644
--- a/Src/DasherCore/ControlManager.h
+++ b/Src/DasherCore/ControlManager.h
@@ -95,6 +95,7 @@ namespace Dasher {
///
virtual void PopulateChildren();
+ virtual int ExpectedNumChildren();
virtual void Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization );
virtual void Undo();
diff --git a/Src/DasherCore/ConversionHelper.cpp b/Src/DasherCore/ConversionHelper.cpp
index 03c1ac3..e09af69 100644
--- a/Src/DasherCore/ConversionHelper.cpp
+++ b/Src/DasherCore/ConversionHelper.cpp
@@ -72,100 +72,9 @@ CConversionManager::CConvNode *CConversionHelper::GetRoot(CDasherNode *pParent,
// TODO: This function needs to be significantly tidied up
// TODO: get rid of pSizes
-void CConversionHelper::AssignChildSizes(SCENode **pNode, CLanguageModel::Context context, int iNChildren) {
-
- // Calculate sizes for the children. Note that normalisation is
- // done additiviely rather than multiplicatively, so it's not
- // quite what was originally planned (but I don't think this is
- // much of a problem). More serious is the fact that the ordering
- // is being lost when the tree is created, as nodes begininning
- // with the same character are merged. This needs to be though
- // out, but the probabilities should probably be done at the time
- // of construction of the candidate tree rather than the Dasher
- // tree (aside - is there any real point having two separate trees
- // - surely we should just create Dasher nodes right away?).
- //
- // The algorithm should also allow for the possibility of the
- // conversion engine returning probabilities itself, which should
- // be used in preference to the values infered from the ordering
- //
- // Finally, maybe the choices should be presented in lexographic
- // order, rather than in order returned (really not sure about
- // this - it needs to be thought through).
-
-
- // std::cout << "b" << std::endl;
-
- //TESTING FOR CALCULATESCORE STAGE 1
- //int test;
- //test = CalculateScore(pNode, 1);
- //std::cout<<"current character"<<pCurrentSCENode->pszConversion<<std::endl;
- //std::cout<<"the score for the second candidate is"<<test<<std::endl;
-
-
-
- //ASSIGNING SCORES AND CALCULATING NODE SIZE
- //Ph: feel free to edit this part to make it more structured
-// int iSize[pCurrentSCEChild->IsHeadAndCandNum];
-// int score[pCurrentSCEChild->IsHeadAndCandNum];
-// int total =0;
-// int max = 0;
-// int CandNum = pCurrentSCEChild -> IsHeadAndCandNum;
-
-// CHANGE int iRemaining(m_pNCManager->GetLongParameter(LP_NORMALIZATION));
-
- // Thoughts on the general idea here - this is very close to being
- // a fully fledged language model, so I think we should go with
- // that idea, but maybe we need something mode flexible. I'd
- // imagine:
- //
- // 1. Probabilities provided directly with translation? Maybe hard
- // to represent in the lattice itself.
- //
- // 2. Full n-gram language model provided - in general assign
- // probabilities to paths through the lattice
- //
- // 3. Ordered results, but no probabilities - using a power law
- // rule or the like.
- //
- // Tempted to assume (1) and (2) can be implemented together, with
- // a second call to the library at node creation time, and (3) can
- // be implemented as a fallback if that doesn't work.
- //
- // Things to be thought out:
- // - How to deal with contexts - backtrace at time of call or stored in node?
- // - Sharing of language model infrastructure?
-
-
-
- // Lookup scores for each of the children
-
- // TODO: Reimplement -----
-
- // for(int i(0); i < pCurrentSCEChild->IsHeadAndCandNum; ++i){
- // score[i] = CalculateScore(pNode, i);
- // total += score[i];
- // if(i!=0)
- // if (score[i]>score[i-1])
- // max = score[i];
- // }
-
- // -----
-
- // Use the scores to calculate the size of the nodes
-
-
- iNChildren = 0;
- SCENode *pChild(*pNode);
-
- while(pChild) {
- pChild = pChild->GetNext();
- ++iNChildren;
- }
-
- // std::cout<<"iNChildren: "<<iNChildren<<std::endl;
- AssignSizes(pNode, context, m_pNCManager->GetLongParameter(LP_NORMALIZATION), m_pNCManager->GetLongParameter(LP_UNIFORM), iNChildren);
+void CConversionHelper::AssignChildSizes(const std::vector<SCENode *> &nodes, CLanguageModel::Context context) {
+ AssignSizes(nodes, context, m_pNCManager->GetLongParameter(LP_NORMALIZATION), m_pNCManager->GetLongParameter(LP_UNIFORM));
}
@@ -177,47 +86,16 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
//
- if(bisRoot) {
+ if(bisRoot && !pSCENode) {
mgr()->BuildTree(this);
}
- SCENode *pCurrentSCEChild;
-
- if(pSCENode){
+ if(pSCENode && !pSCENode->GetChildren().empty()) {
+ const std::vector<SCENode *> &vChildren = pSCENode->GetChildren();
// RecursiveDumpTree(pSCENode, 1);
- pCurrentSCEChild = pSCENode->GetChild();
-
- }
- else {
- // if(m_pRoot && !pCurrentDataNode->bType)
- // pCurrentSCEChild = m_pRoot[0];
- //else
- pCurrentSCEChild = 0;
- }
-
- if(pCurrentSCEChild) {
- // std::cout<<"Populating character nodes!"<<std::endl;
- // std::cout << "Current SCE Child: " << pCurrentSCEChild << std::endl;
-
- // TODO: Reimplement (in subclass) -----
-
-// if(m_iHZCount>1)
-// if(!m_bPhrasesProcessed[pCurrentSCEChild->AcCharCount-1])
-// if(pCurrentSCEChild->AcCharCount<m_iHZCount)
-// ProcessPhrase(pCurrentSCEChild->AcCharCount-1);
-
- // -----
-
- //int *iSize;
-
- // iSize = new int[pCurrentSCEChild->IsHeadAndCandNum];
-
-
-
-
- mgr()->AssignChildSizes(&pCurrentSCEChild, iContext, pCurrentSCEChild->IsHeadAndCandNum);
-
+ mgr()->AssignChildSizes(vChildren, iContext);
+
int iIdx(0);
int iCum(0);
@@ -227,9 +105,10 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
// Finally loop through and create the children
- do {
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
// std::cout << "Current scec: " << pCurrentSCEChild << std::endl;
-
+ SCENode *pCurrentSCEChild(*it);
+ DASHER_ASSERT(pCurrentSCEChild != NULL);
int iLbnd(iCum);
int iHbnd(iCum + pCurrentSCEChild->NodeSize);
//m_pNCManager->GetLongParameter(LP_NORMALIZATION));//
@@ -263,24 +142,22 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
pNewNode->m_iOffset = m_iOffset + 1;
if(pLanguageModel) {
- CLanguageModel::Context iContext;
- iContext = pLanguageModel->CloneContext(this->iContext);
-
- if(pCurrentSCEChild ->Symbol !=-1)
- pNewNode->pLanguageModel->EnterSymbol(iContext, pCurrentSCEChild->Symbol); // TODO: Don't use symbols?
-
-
- pNewNode->iContext = iContext;
+ CLanguageModel::Context iContext;
+ iContext = pLanguageModel->CloneContext(this->iContext);
+
+ if(pCurrentSCEChild ->Symbol !=-1)
+ pNewNode->pLanguageModel->EnterSymbol(iContext, pCurrentSCEChild->Symbol); // TODO: Don't use symbols?
+
+
+ pNewNode->iContext = iContext;
}
DASHER_ASSERT(GetChildren().back()==pNewNode);
- pCurrentSCEChild = pCurrentSCEChild->GetNext();
++iIdx;
- }while(pCurrentSCEChild);
+ }
}
-
else {//End of conversion -> default to alphabet
//Phil//
@@ -292,6 +169,11 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
CConvNode::PopulateChildren();
}
}
+int CConversionHelper::CConvHNode::ExpectedNumChildren() {
+ if(bisRoot && !pSCENode) mgr()->BuildTree(this);
+ if (pSCENode && !pSCENode->GetChildren().empty()) return pSCENode->GetChildren().size();
+ return CConvNode::ExpectedNumChildren();
+}
void CConversionHelper::BuildTree(CConvHNode *pRoot) {
// Build the string to convert.
diff --git a/Src/DasherCore/ConversionHelper.h b/Src/DasherCore/ConversionHelper.h
index f514bee..04f6c7e 100644
--- a/Src/DasherCore/ConversionHelper.h
+++ b/Src/DasherCore/ConversionHelper.h
@@ -65,9 +65,8 @@ namespace Dasher{
/// @param context Unsure - document this, shouldn't be in general class (include userdata pointer).
/// @param normalization Normalisation constant for the child sizes (TODO: check that this is a sensible value, ie the same as Dasher normalisation).
/// @param uniform Unsure - document this.
- /// @param iNChildren The number of children to be expected (more efficient than iterating linked list).
///
- virtual void AssignSizes(SCENode ** pStart, Dasher::CLanguageModel::Context context, long normalization, int uniform, int iNChildren)=0;
+ virtual void AssignSizes(const std::vector<SCENode *> &vChildren, Dasher::CLanguageModel::Context context, long normalization, int uniform)=0;
/// Assign colours to the children of a given conversion node.
/// This function needs a rethink.
@@ -109,7 +108,7 @@ namespace Dasher{
/// normalisation constant
///
- virtual void AssignChildSizes(SCENode **pNode, CLanguageModel::Context context, int iNChildren);
+ virtual void AssignChildSizes(const std::vector<SCENode *> &vChildren, CLanguageModel::Context context);
protected:
class CConvHNode : public CConvNode {
@@ -119,7 +118,7 @@ namespace Dasher{
/// Provide children for the supplied node
///
virtual void PopulateChildren();
-
+ virtual int ExpectedNumChildren();
virtual void SetFlag(int iFlag, bool bValue);
protected:
inline CConversionHelper *mgr() {return static_cast<CConversionHelper *>(m_pMgr);}
diff --git a/Src/DasherCore/ConversionManager.cpp b/Src/DasherCore/ConversionManager.cpp
index 9b89b55..13d912c 100644
--- a/Src/DasherCore/ConversionManager.cpp
+++ b/Src/DasherCore/ConversionManager.cpp
@@ -107,6 +107,9 @@ void CConversionManager::CConvNode::PopulateChildren() {
DASHER_ASSERT(GetChildren().back()==pNewNode);
}
+int CConversionManager::CConvNode::ExpectedNumChildren() {
+ return 1; //the alphabet root
+}
CConversionManager::CConvNode::~CConvNode() {
pLanguageModel->ReleaseContext(iContext);
@@ -114,25 +117,14 @@ CConversionManager::CConvNode::~CConvNode() {
}
void CConversionManager::RecursiveDumpTree(SCENode *pCurrent, unsigned int iDepth) {
- pCurrent = pCurrent->GetChild();
-
- if(pCurrent){
- while(pCurrent){
- std::cout << " " << pCurrent->pszConversion << " " << pCurrent->IsHeadAndCandNum << " " << pCurrent->CandIndex << " " << pCurrent->IsComplete << " " << pCurrent->AcCharCount << std::endl;
- pCurrent = pCurrent->GetNext();
- }
- }
- /*
- while(pCurrent) {
+ const std::vector<SCENode *> &children = pCurrent->GetChildren();
+ for (std::vector<SCENode *>::const_iterator it = children.begin(); it!=children.end(); it++) {
+ SCENode *pCurrent(*it);
for(unsigned int i(0); i < iDepth; ++i)
std::cout << "-";
-
std::cout << " " << pCurrent->pszConversion << " " << pCurrent->IsHeadAndCandNum << " " << pCurrent->CandIndex << " " << pCurrent->IsComplete << " " << pCurrent->AcCharCount << std::endl;
-
- RecursiveDumpTree(pCurrent->GetChild(), iDepth + 1);
- pCurrent = pCurrent->GetNext();
+ RecursiveDumpTree(pCurrent, iDepth + 1);
}
- */
}
void CConversionManager::CConvNode::GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength) {
diff --git a/Src/DasherCore/ConversionManager.h b/Src/DasherCore/ConversionManager.h
index de88c91..a820dd7 100644
--- a/Src/DasherCore/ConversionManager.h
+++ b/Src/DasherCore/ConversionManager.h
@@ -87,6 +87,7 @@ namespace Dasher {
///
virtual void PopulateChildren();
+ virtual int ExpectedNumChildren();
~CConvNode();
diff --git a/Src/DasherCore/DasherModel.cpp b/Src/DasherCore/DasherModel.cpp
index 94d929e..d9ecc13 100644
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@ -719,18 +719,10 @@ bool CDasherModel::RenderToView(CDasherView *pView, NodeQueue &nodeQueue) {
//(however, note that doing this here will only expand one level per frame,
//and won't really take effect until the *next* frame!)
int iNodeBudget = GetLongParameter(LP_NODE_BUDGET);
- //note: the 'number of symbols' is the number of leaves in the subtree created by
- //expanding a node, i.e. excluding group nodes; it also counts only 1 for both
- //the node at the root of any control mode group, *and* the same for any conversion node.
- //So, expanding a node could create significantly more children than this.
- //Doubling this is arbitrary, but I'm just hoping it's a reasonably upper bound for the
- //number of descendants that'll actually be created; if expansion creates more nodes than
- //this, the logic below will perform one more contraction, and expansion, per frame than
- //we want - a performance issue, but hopefully not a correctness issue ;-).
- int iExpansion = m_pNodeCreationManager->GetAlphabet()->GetNumberSymbols()*2;
+
//first, make sure we are within our budget (probably only in case the budget's changed)
while (nodeQueue.hasNodesToCollapse()
- && currentNumNodeObjects() > iNodeBudget + iExpansion)
+ && currentNumNodeObjects() > iNodeBudget)
{
nodeQueue.nodeToCollapse()->Delete_children();
nodeQueue.popNodeToCollapse();
@@ -740,7 +732,7 @@ bool CDasherModel::RenderToView(CDasherView *pView, NodeQueue &nodeQueue) {
//nodes to expand (as zero-cost collapses have already been performed)
while (nodeQueue.hasNodesToExpand())
{
- if (currentNumNodeObjects() < iNodeBudget)
+ if (currentNumNodeObjects() + nodeQueue.nodeToExpand()->ExpectedNumChildren() < iNodeBudget)
{
Push_Node(nodeQueue.nodeToExpand());
nodeQueue.popNodeToExpand();
diff --git a/Src/DasherCore/DasherNode.h b/Src/DasherCore/DasherNode.h
index 1692aec..ce8215c 100644
--- a/Src/DasherCore/DasherNode.h
+++ b/Src/DasherCore/DasherNode.h
@@ -228,6 +228,11 @@ class Dasher::CDasherNode:private NoClones {
///
virtual void PopulateChildren() = 0;
+
+ /// The number of children which a call to PopulateChildren can be expected to generate.
+ /// (This is not required to be 100% accurate, but any discrepancies will likely cause
+ /// the node budgetting algorithm to behave sub-optimally)
+ virtual int ExpectedNumChildren() = 0;
///
/// Called whenever a node belonging to this manager first
diff --git a/Src/DasherCore/DasherViewSquare.cpp b/Src/DasherCore/DasherViewSquare.cpp
index 235ee4a..bb4d640 100644
--- a/Src/DasherCore/DasherViewSquare.cpp
+++ b/Src/DasherCore/DasherViewSquare.cpp
@@ -308,9 +308,7 @@ void CDasherViewSquare::RecursiveRender(CDasherNode *pRender, myint y1, myint y2
int id=-1;
// int lower=-1,upper=-1;
myint temp_parentwidth=y2-y1;
- int temp_parentcolor = (pRender->GetDisplayInfo()->bVisible)
- ? pRender->GetDisplayInfo()->iColour
- : parent_color;
+ int temp_parentcolor = pRender->GetDisplayInfo()->iColour;
const int Range(y2 - y1);
@@ -382,7 +380,7 @@ void CDasherViewSquare::RecursiveRender(CDasherNode *pRender, myint y1, myint y2
}
}
// Draw the outline
- if(!(pRender->GetFlag(NF_SUBNODE))) {
+ if(pRender->GetDisplayInfo()->bVisible && !(pRender->GetFlag(NF_SUBNODE))) {
RenderNodeOutlineFast(pRender->GetDisplayInfo()->iColour,
y1, y2, mostleft,
pRender->GetDisplayInfo()->strDisplayText,
diff --git a/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.cpp b/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.cpp
index 64a84c5..169469e 100644
--- a/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.cpp
+++ b/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.cpp
@@ -187,14 +187,11 @@ void CPPMPYLanguageModel::GetProbs(Context context, std::vector<unsigned int> &p
DASHER_ASSERT(iToSpend == 0);
}
-void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int iNumSymbols, int norm, int iUniform){
+void CPPMPYLanguageModel::GetPartProbs(Context context, const std::vector<SCENode *> &vChildren, int norm, int iUniform){
- SCENode * pNewStart = *pStart;
- SCENode * pNode = pNewStart;
-
- if(iNumSymbols == 1){
- pNode->NodeSize = norm;
+ if(vChildren.size() == 1){
+ vChildren[0]->NodeSize = norm;
return;
}
// std::cout<<"Norms is "<<norm<<std::endl;
@@ -209,7 +206,7 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
// probs.resize(iNumSymbols);
// Leave the vector treatment for now
- std::vector < bool > exclusions(iNumSymbols);
+ std::vector < bool > exclusions(vChildren.size());
unsigned int iToSpend = norm;
unsigned int iUniformLeft = iUniform;
@@ -219,20 +216,18 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
//Reproduce iterative calculations with SCENode trie
- if(pNode){
- pNode -> NodeSize = 0;
- pNode = pNode->GetNext();
- }
-
- int i =1;
- while(pNode){
- pNode->NodeSize = iUniformLeft / (iNumSymbols - i);
- // std::cout<<"iUniformLeft: "<<iUniformLeft<<std::endl;
- iUniformLeft -= pNode->NodeSize;
- iToSpend -= pNode->NodeSize;
- exclusions[i] = false;
- pNode =pNode->GetNext();
- i++;
+ if(vChildren.size()){
+ vChildren[0] -> NodeSize = 0;
+ int i=1;
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin()+1; it!=vChildren.end(); it++) {
+ SCENode *pNode(*it);
+ pNode->NodeSize = iUniformLeft / (vChildren.size() - i);
+ // std::cout<<"iUniformLeft: "<<iUniformLeft<<std::endl;
+ iUniformLeft -= pNode->NodeSize;
+ iToSpend -= pNode->NodeSize;
+ exclusions[i] = false;
+ i++;
+ }
}
DASHER_ASSERT(iUniformLeft == 0);
@@ -251,10 +246,9 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
while(pTemp!=0){
int iTotal =0;
vNodeStore.clear();
-
- pNode = pNewStart;
- i=0;
- while(pNode){
+ int i=0;
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+ SCENode *pNode(*it);
pFound = pTemp->find_symbol(pNode->Symbol);
//Mark: do we need to treat the exception of -1 separately?
@@ -265,7 +259,6 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
else
vNodeStore.push_back(NULL);
- pNode= pNode->GetNext();
i++;
}
@@ -274,19 +267,18 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
if(iTotal){
unsigned int size_of_slice = iToSpend;
- i=0;
- pNode=pNewStart;
- while(pNode){
- if((!(exclusions[i] && doExclusion))&&(vNodeStore[i])) {
- exclusions[i] = 1;
- unsigned int p = static_cast < myint > (size_of_slice) * (100 * vNodeStore[i]->count - beta) / (100 * iTotal + alpha);
- if((pNode->Symbol>-1)&&(pNode->Symbol<=m_iAlphSize)){
- pNode->NodeSize += p;
- iToSpend -= p;
- }
- }
- pNode= pNode->GetNext();
- i++;
+ int i=0;
+ for (vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+ SCENode *pNode(*it);
+ if((!(exclusions[i] && doExclusion))&&(vNodeStore[i])) {
+ exclusions[i] = 1;
+ unsigned int p = static_cast < myint > (size_of_slice) * (100 * vNodeStore[i]->count - beta) / (100 * iTotal + alpha);
+ if((pNode->Symbol>-1)&&(pNode->Symbol<=m_iAlphSize)){
+ pNode->NodeSize += p;
+ iToSpend -= p;
+ }
+ }
+ i++;
}
}
pTemp = pTemp->vine;
@@ -298,7 +290,7 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
unsigned int size_of_slice = iToSpend;
int symbolsleft = 0;
- for(i = 1; i < iNumSymbols; i++)
+ for(unsigned int i = 1; i < vChildren.size(); i++)
if(!(exclusions[i] && doExclusion))
symbolsleft++;
@@ -316,35 +308,32 @@ void CPPMPYLanguageModel::GetPartProbs(Context context, SCENode ** pStart, int i
// DASHER_TRACEOUTPUT("valid %s",str2.str().c_str());
//std::cout<<"after lan mod third loop"<<std::endl;
- if(pNewStart)
- pNode = pNewStart->GetNext();
-
- i=1;
- while(pNode){
- if(!(exclusions[i] && doExclusion)) {
- unsigned int p = size_of_slice / symbolsleft;
- pNode->NodeSize += p;
- iToSpend -= p;
+ if(vChildren.size()) {
+ int i=1;
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin()+1; it!=vChildren.end(); it++) {
+ if(!(exclusions[i] && doExclusion)) {
+ unsigned int p = size_of_slice / symbolsleft;
+ (*it)->NodeSize += p;
+ iToSpend -= p;
+ }
+ i++;
}
- pNode = pNode->GetNext();
- i++;
}
// std::cout<<"after lan mod fourth loop"<<std::endl;
- int iLeft = iNumSymbols-1;
+ int iLeft = vChildren.size()-1;
- if(pNewStart)
- pNode = pNewStart->GetNext();
- // std::cout<<"iNumsyjbols "<<iNumSymbols<<std::endl;
+ if(vChildren.size()) {
+ // std::cout<<"iNumsyjbols "<<vChildren.size()<<std::endl;
- while(pNode){
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin()+1; it!=vChildren.end(); it++) {
- // std::cout<<"iLeft "<<iLeft<<std::endl;
- // std::cout<<"iToSpend "<<iToSpend<<std::endl;
- unsigned int p = iToSpend / iLeft;
- pNode->NodeSize += p;
- --iLeft;
- iToSpend -= p;
- pNode = pNode->GetNext();
+ // std::cout<<"iLeft "<<iLeft<<std::endl;
+ // std::cout<<"iToSpend "<<iToSpend<<std::endl;
+ unsigned int p = iToSpend / iLeft;
+ (*it)->NodeSize += p;
+ --iLeft;
+ iToSpend -= p;
+ }
}
//std::cout<<"after lan mod fifth loop"<<std::endl;
diff --git a/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.h b/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.h
index 94f466f..1fe2c42 100644
--- a/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.h
+++ b/Src/DasherCore/LanguageModelling/PPMPYLanguageModel.h
@@ -90,7 +90,7 @@ namespace Dasher {
virtual void GetProbs(Context context, std::vector < unsigned int >&Probs, int norm, int iUniform) const;
void GetPYProbs(Context context, std::vector < unsigned int >&Probs, int norm, int iUniform);
- void GetPartProbs(Context context, SCENode **pStart, int iNumSymbols, int norm, int iUniform);
+ void GetPartProbs(Context context, const std::vector<SCENode *> &vChildren, int norm, int iUniform);
void dump();
diff --git a/Src/DasherCore/MandarinAlphMgr.cpp b/Src/DasherCore/MandarinAlphMgr.cpp
index 85833b7..3967ca5 100644
--- a/Src/DasherCore/MandarinAlphMgr.cpp
+++ b/Src/DasherCore/MandarinAlphMgr.cpp
@@ -61,10 +61,9 @@ CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, int
pDispInfo->bVisible = true;
pDispInfo->strDisplayText = "";
pDispInfo->iColour = m_pNCManager->GetAlphabet()->GetColour(0, 0);
- pNewNode = makeNode(pParent, iLower, iUpper, pDispInfo);
+ pNewNode = makeGroup(pParent, iLower, iUpper, pDispInfo, NULL);
pNewNode->m_iOffset=max(0,iOffset)-1;
pNewNode->iPhase=0;
- pNewNode->iSymbol=0;
} else {
//probably rebuilding parent; call standard GetRoot, which'll extract the most recent symbol
// (entered by the node (equivalent to that) which we are rebuilding)
@@ -83,9 +82,9 @@ CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, int
return pNewNode;
}
-CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd) {
- if (iSymbol <= 1288 && iSymbol != iExistingSymbol) {
+ if (iSymbol <= 1288) {
//Will wrote:
//Modified for Mandarin Dasher
//The following logic switch allows punctuation nodes in Mandarin to be treated in the same way as English (i.e. display and populate next round) instead of invoking a conversion node
@@ -95,7 +94,7 @@ CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymb
static_cast<CPinYinConversionHelper::CPYConvNode *>(pNewNode)->SetConvSymbol(iSymbol);
return pNewNode;
}
- return CAlphabetManager::CreateSymbolNode(pParent, iSymbol, iLbnd, iHbnd, iExistingSymbol, pExistingChild);
+ return CAlphabetManager::CreateSymbolNode(pParent, iSymbol, iLbnd, iHbnd);
}
CLanguageModel::Context CMandarinAlphMgr::CreateSymbolContext(CAlphNode *pParent, symbol iSymbol)
@@ -104,12 +103,12 @@ CLanguageModel::Context CMandarinAlphMgr::CreateSymbolContext(CAlphNode *pParent
return m_pLanguageModel->CloneContext(pParent->iContext);
}
-CMandarinAlphMgr::CMandNode::CMandNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr)
-: CAlphNode(pParent, iLbnd, iHbnd, pDispInfo, pMgr) {
+CMandarinAlphMgr::CMandNode::CMandNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr, symbol iSymbol)
+: CSymbolNode(pParent, iLbnd, iHbnd, pDispInfo, pMgr, iSymbol) {
}
-CAlphabetManager::CAlphNode *CMandarinAlphMgr::makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo) {
- return new CMandNode(pParent, iLbnd, iHbnd, pDispInfo, this);
+CAlphabetManager::CSymbolNode *CMandarinAlphMgr::makeSymbol(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, symbol iSymbol) {
+ return new CMandNode(pParent, iLbnd, iHbnd, pDispInfo, this, iSymbol);
}
void CMandarinAlphMgr::CMandNode::SetFlag(int iFlag, bool bValue) {
diff --git a/Src/DasherCore/MandarinAlphMgr.h b/Src/DasherCore/MandarinAlphMgr.h
index a54c5a9..906b02d 100644
--- a/Src/DasherCore/MandarinAlphMgr.h
+++ b/Src/DasherCore/MandarinAlphMgr.h
@@ -44,13 +44,13 @@ namespace Dasher {
virtual CAlphNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset);
protected:
- class CMandNode : public CAlphNode {
+ class CMandNode : public CSymbolNode {
public:
- CMandNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr);
+ CMandNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr, symbol iSymbol);
virtual void SetFlag(int iFlag, bool bValue);
};
- CAlphNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
- virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild);
+ CSymbolNode *makeSymbol(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, symbol iSymbol);
+ virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd);
virtual CLanguageModel::Context CreateSymbolContext(CAlphNode *pParent, symbol iSymbol);
};
/// @}
diff --git a/Src/DasherCore/NodeCreationManager.cpp b/Src/DasherCore/NodeCreationManager.cpp
index 8a417ba..0bdc3e0 100644
--- a/Src/DasherCore/NodeCreationManager.cpp
+++ b/Src/DasherCore/NodeCreationManager.cpp
@@ -196,20 +196,13 @@ CDasherNode *CNodeCreationManager::GetConvRoot(Dasher::CDasherNode *pParent, int
return NULL;
}
-void CNodeCreationManager::GetProbs(CLanguageModel::Context context, std::vector <symbol >&NewSymbols, std::vector <unsigned int >&Probs, int iNorm) const {
+void CNodeCreationManager::GetProbs(CLanguageModel::Context context, std::vector <unsigned int >&Probs, int iNorm) const {
// Total number of symbols
int iSymbols = m_pAlphabet->GetNumberSymbols(); // note that this includes the control node and the root node
// Number of text symbols, for which the language model gives the distribution
// int iTextSymbols = m_pAlphabet->GetNumberTextSymbols();
- NewSymbols.resize(iSymbols);
-// Groups.resize(iSymbols);
- for(int i = 0; i < iSymbols; i++) {
- NewSymbols[i] = i; // This will be replaced by something that works out valid nodes for this context
- // Groups[i]=m_pAlphabet->get_group(i);
- }
-
// TODO - sort out size of control node - for the timebeing I'll fix the control node at 5%
// TODO: New method (see commented code) has been removed as it wasn' working.
diff --git a/Src/DasherCore/NodeCreationManager.h b/Src/DasherCore/NodeCreationManager.h
index 43db392..8bfd194 100644
--- a/Src/DasherCore/NodeCreationManager.h
+++ b/Src/DasherCore/NodeCreationManager.h
@@ -54,7 +54,7 @@ class CNodeCreationManager : public Dasher::CDasherComponent {
void DisconnectNode(int iChild, int iParent);
- void GetProbs(Dasher::CLanguageModel::Context context, std::vector <Dasher::symbol >&NewSymbols, std::vector <unsigned int >&Probs, int iNorm) const;
+ void GetProbs(Dasher::CLanguageModel::Context context, std::vector <unsigned int >&Probs, int iNorm) const;
///
/// Get a reference to the alphabet
diff --git a/Src/DasherCore/PinYinConversionHelper.cpp b/Src/DasherCore/PinYinConversionHelper.cpp
index 32e8f04..f0ce267 100644
--- a/Src/DasherCore/PinYinConversionHelper.cpp
+++ b/Src/DasherCore/PinYinConversionHelper.cpp
@@ -75,16 +75,15 @@ bool CPinYinConversionHelper::Convert(const std::string &strSource, SCENode ** p
return (pParser && pParser->Convert(strSource, pRoot));
}
-unsigned int CPinYinConversionHelper::GetSumPYProbs(Dasher::CLanguageModel::Context context, SCENode * pPYCandStart, int norm){
+unsigned int CPinYinConversionHelper::GetSumPYProbs(Dasher::CLanguageModel::Context context, std::vector<SCENode *> &pPYCandStart, int norm){
std::vector <unsigned int> Probs;
unsigned int sumProb=0;
GetLanguageModel()->GetProbs(context, Probs, norm, 0);
- SCENode * pCurrentNode = pPYCandStart;
-
- while(pCurrentNode){
+ for (std::vector<SCENode *>::iterator it = pPYCandStart.begin(); it != pPYCandStart.end(); it++) {
+ SCENode *pCurrentNode(*it);
std::vector <symbol >Symbols;
std::string HZ = static_cast<std::string>(pCurrentNode->pszConversion);
@@ -94,7 +93,6 @@ unsigned int CPinYinConversionHelper::GetSumPYProbs(Dasher::CLanguageModel::Cont
if(Symbols.size()!=0)
sumProb += Probs[Symbols[0]];
- pCurrentNode = pCurrentNode->GetNext();
}
@@ -104,21 +102,16 @@ unsigned int CPinYinConversionHelper::GetSumPYProbs(Dasher::CLanguageModel::Cont
void CPinYinConversionHelper::GetProbs(Dasher::CLanguageModel::Context context, std::vector < unsigned int >&Probs, int norm){
}
-void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageModel::Context context, long normalization, int uniform, int iNChildren){
+void CPinYinConversionHelper::AssignSizes(const std::vector<SCENode *> &vChildren, Dasher::CLanguageModel::Context context, long normalization, int uniform){
//test print:
int print = 0;
- SCENode *pNewStart = *pStart;
-
- SCENode *pNode = pNewStart;
-
-
// std::cout<<"Head node "<<pNewStart->pszConversion<<std::endl;
std::vector <unsigned int> Probs;
int iSymbols = m_pCHAlphabet->GetNumberSymbols();
- int iLeft(iNChildren);
+ int iLeft(vChildren.size());
int iRemaining(normalization);
int uniform_add;
@@ -137,8 +130,8 @@ void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageMod
//CLanguageModel::Context iCurrentContext;
// int iNumSymbols =0;
- while(pNode){
-
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+ SCENode *pNode(*it);
Symbols.clear();
std::string HZ(pNode->pszConversion);
@@ -150,24 +143,18 @@ void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageMod
}
else
pNode->Symbol = -1;
-
- pNode = pNode->GetNext();
}
// std::cout<<"size of symbolstore "<<SymbolStore.size()<<std::endl;
// std::cout<<"norm input: "<<nonuniform_norm/(iSymbols/iNChildren/100)<<std::endl;
- GetLanguageModel()->GetPartProbs(context, pStart, iNChildren, nonuniform_norm, 0);
+ GetLanguageModel()->GetPartProbs(context, vChildren, nonuniform_norm, 0);
//std::cout<<"after get probs "<<std::endl;
- pNode = pNewStart;
- while(pNode){
- sumProb += pNode->NodeSize;
-
- // std::cout<<"Nodesize: "<<pNode->NodeSize<<std::endl;
- pNode = pNode->GetNext();
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+ sumProb += (*it)->NodeSize;
}
// std::cout<<"Sum Prob "<<sumProb<<std::endl;
@@ -180,8 +167,8 @@ void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageMod
if(print)
std::cout<<"sumProb "<<sumProb<<std::endl;
- pNode = pNewStart;
- while(pNode){
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+ SCENode *pNode(*it);
if((pNode->Symbol!=-1)&&(sumProb!=0)){
// std::cout<<"Probs size "<<pNode->NodeSize<<std::endl;
pNode->NodeSize = static_cast<unsigned long long int>(pNode->NodeSize*(normalization/sumProb));//*(100 - m_iPriorityScale * pNode->GetPriority())
@@ -207,8 +194,6 @@ void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageMod
// std::cout<<"Symbol i"<<SymbolStore[iIdx]<<std::endl;
// std::cout<<"symbols size "<<SymbolStore.size()<<std::endl;
// std::cout<<"Symbols address "<<&SymbolStore<<std::endl;
-
- pNode = pNode->GetNext();
}
if(print)
@@ -219,8 +204,8 @@ void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageMod
- pNode = pNewStart;
- while(pNode){
+ for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+ SCENode *pNode(*it);
int iDiff(iRemaining / iLeft);
pNode->NodeSize += iDiff;
@@ -230,7 +215,6 @@ void CPinYinConversionHelper::AssignSizes(SCENode **pStart, Dasher::CLanguageMod
// std::cout<<"Node size for "<<pNode->pszConversion<<std::endl;
//std::cout<<"is "<<pNode->NodeSize<<std::endl;
- pNode = pNode->GetNext();
}
}
diff --git a/Src/DasherCore/PinYinConversionHelper.h b/Src/DasherCore/PinYinConversionHelper.h
index b617047..4a48e0c 100644
--- a/Src/DasherCore/PinYinConversionHelper.h
+++ b/Src/DasherCore/PinYinConversionHelper.h
@@ -25,11 +25,11 @@ class CPinYinConversionHelper : public CConversionHelper {
virtual bool Convert(const std::string &strSource, SCENode ** pRoot);
- virtual void AssignSizes(SCENode **pStart, Dasher::CLanguageModel::Context context , long normalization, int uniform, int iNChildren);
+ virtual void AssignSizes(const std::vector<SCENode *> &vChildren, Dasher::CLanguageModel::Context context , long normalization, int uniform);
virtual void GetProbs(Dasher::CLanguageModel::Context context, std::vector < unsigned int >&Probs, int norm);
- virtual unsigned int GetSumPYProbs(Dasher::CLanguageModel::Context context, SCENode * pPYCandStart,int norm);
+ virtual unsigned int GetSumPYProbs(Dasher::CLanguageModel::Context context, std::vector <SCENode *> &pPYCandStart,int norm);
protected:
class CPYConvNode : public CConvHNode {
diff --git a/Src/DasherCore/PinyinParser.cpp b/Src/DasherCore/PinyinParser.cpp
index 8c2a415..564a9bd 100644
--- a/Src/DasherCore/PinyinParser.cpp
+++ b/Src/DasherCore/PinyinParser.cpp
@@ -171,13 +171,10 @@ bool CPinyinParser::Convert(const std::string &pystr, SCENode **pRoot) {
return 0;
*pRoot = new SCENode;
- SCENode *pCurrent = *pRoot;
-
- pCurrent->pszConversion = "";
- SCENode *pNewNode = new SCENode;
- pCurrent->SetChild(pNewNode);
+ (*pRoot)->pszConversion = "";
for(std::set<std::string>::iterator it = pCurrentNode->m_pList->begin(); it != pCurrentNode->m_pList->end(); ++it) {
+ SCENode *pNewNode = new SCENode;
pNewNode->pszConversion = new char[it->size() + 1];
strcpy(pNewNode->pszConversion, it->c_str());
@@ -187,14 +184,9 @@ bool CPinyinParser::Convert(const std::string &pystr, SCENode **pRoot) {
// std::vector<int> CHSym;
// m_pCHAlphabet->GetSymbols(&CHSym, &strChar, 0);
// pNewNode->Symbol = CHSym[0];
-
- pCurrent = pNewNode;
- pNewNode = new SCENode;
- pCurrent->SetNext(pNewNode);
- pCurrent->SetChild(NULL);
+ (*pRoot)->AddChild(pNewNode);
}
- pCurrent->SetNext(NULL);
//Test code: will make program crash
// SCENode * pTemp = *pRoot;
diff --git a/Src/DasherCore/SCENode.cpp b/Src/DasherCore/SCENode.cpp
index f47c448..cc3cffc 100644
--- a/Src/DasherCore/SCENode.cpp
+++ b/Src/DasherCore/SCENode.cpp
@@ -21,39 +21,12 @@
#include "SCENode.h"
SCENode::SCENode() {
- m_pNext = 0;
- m_pChild = 0;
-
m_iRefCount = 1;
}
SCENode::~SCENode() {
// TODO: Delete string?
- if(m_pNext)
- m_pNext->Unref();
-
- if(m_pChild)
- m_pChild->Unref();
+ for (std::vector<SCENode *>::iterator it = m_vChildren.begin(); it!=m_vChildren.end(); it++)
+ (*it)->Unref();
}
-
-void SCENode::SetNext(SCENode *pNext) {
- if(m_pNext)
- m_pNext->Unref();
-
- m_pNext = pNext;
-
- if(m_pNext)
- m_pNext->Ref();
-};
-
-void SCENode::SetChild(SCENode *pChild) {
- if(m_pChild)
- m_pChild->Unref();
-
- m_pChild = pChild;
-
- if(m_pChild)
- m_pChild->Ref();
-};
-
diff --git a/Src/DasherCore/SCENode.h b/Src/DasherCore/SCENode.h
index b3dda13..b7dcbfb 100644
--- a/Src/DasherCore/SCENode.h
+++ b/Src/DasherCore/SCENode.h
@@ -24,6 +24,8 @@
/*Common Node Definition for Chinese Pinyin (possibly also Japanese)
Conversion Library and Dasher ConversionManager*/
+#include <vector>
+
/// \ingroup Model
/// \{
class SCENode {
@@ -44,17 +46,13 @@ class SCENode {
}
};
- SCENode *GetNext() {
- return m_pNext;
- };
-
- void SetNext(SCENode *pNext);
-
- SCENode *GetChild() {
- return m_pChild;
- };
-
- void SetChild(SCENode *pChild);
+ const std::vector<SCENode *> &GetChildren() const {
+ return m_vChildren;
+ }
+ void AddChild(SCENode *pChild) {
+ m_vChildren.push_back(pChild);
+ pChild->Ref();
+ }
void SetPriority(int iPriority) {
m_iPriority = iPriority;
@@ -81,8 +79,7 @@ class SCENode {
private:
int m_iRefCount;
- SCENode *m_pNext;
- SCENode *m_pChild;
+ std::vector<SCENode *> m_vChildren;
int m_iPriority;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]