306 lines
6.2 KiB
C++
306 lines
6.2 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1998
|
||
|
//
|
||
|
// File: mddist.cpp
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
//
|
||
|
// MDDIST.CPP
|
||
|
//
|
||
|
|
||
|
#include <basetsd.h>
|
||
|
#include <iostream>
|
||
|
#include <fstream>
|
||
|
|
||
|
#include "symtmbn.h"
|
||
|
|
||
|
LEAK_VAR_DEF(BNDIST)
|
||
|
|
||
|
static void dumpVimd ( const VIMD & vimd )
|
||
|
{
|
||
|
for ( int i = 0 ; i < vimd.size(); i++ )
|
||
|
{
|
||
|
cout << vimd[i];
|
||
|
if ( i + 1 < vimd.size() )
|
||
|
cout << ",";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void dumpVlr ( const VLREAL & vlr )
|
||
|
{
|
||
|
for ( int i = 0 ; i < vlr.size(); i++ )
|
||
|
{
|
||
|
cout << vlr[i];
|
||
|
if ( i + 1 < vlr.size() )
|
||
|
cout << ",";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void dumpSlice ( const MDVSLICE & mslice, bool bStrides = true)
|
||
|
{
|
||
|
VIMD vimdLengths = mslice.size();
|
||
|
VIMD vimdStrides = mslice.stride();
|
||
|
size_t iStart = mslice.start();
|
||
|
|
||
|
cout << "\nslice start="
|
||
|
<< iStart
|
||
|
<< "\tlengths=";
|
||
|
dumpVimd( vimdLengths );
|
||
|
if ( bStrides )
|
||
|
{
|
||
|
cout << "\tstrides=" ;
|
||
|
dumpVimd( vimdStrides );
|
||
|
}
|
||
|
cout << "\ttotlen="
|
||
|
<< mslice._Totlen();
|
||
|
}
|
||
|
|
||
|
static void dumpMdv ( DISTDD & mdv, const MDVSLICE * pslice = NULL )
|
||
|
{
|
||
|
if ( pslice == NULL )
|
||
|
pslice = & mdv.Slice();
|
||
|
dumpSlice( *pslice );
|
||
|
DISTDD::Iterator itmd(mdv, *pslice );
|
||
|
while (itmd.BNext())
|
||
|
{
|
||
|
size_t icurr = itmd.ICurr();
|
||
|
cout << "\n";
|
||
|
dumpVimd( itmd.Vitmd() );
|
||
|
REAL & r = itmd.Next();
|
||
|
cout << "\t["
|
||
|
<< icurr
|
||
|
<< "] = "
|
||
|
<< r ;
|
||
|
}
|
||
|
cout << "\n";
|
||
|
}
|
||
|
|
||
|
BNDIST :: BNDIST ()
|
||
|
:_edist(ED_NONE),
|
||
|
_pmvd(NULL),
|
||
|
_pdrmap(NULL)
|
||
|
{
|
||
|
LEAK_VAR_UPD(1)
|
||
|
}
|
||
|
|
||
|
BNDIST :: ~ BNDIST ()
|
||
|
{
|
||
|
Clear();
|
||
|
LEAK_VAR_UPD(-1)
|
||
|
}
|
||
|
|
||
|
void BNDIST :: NoRef ()
|
||
|
{
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
BNDIST & BNDIST :: operator = ( const BNDIST & bnd )
|
||
|
{
|
||
|
Clear();
|
||
|
switch ( _edist = bnd._edist )
|
||
|
{
|
||
|
default:
|
||
|
case ED_NONE:
|
||
|
break;
|
||
|
case ED_DENSE:
|
||
|
_pmvd = new DISTDD( bnd.Mvd() );
|
||
|
assert( _pmvd->first.size() == bnd.Mvd().first.size() );
|
||
|
break;
|
||
|
case ED_CI_MAX:
|
||
|
case ED_CI_PLUS:
|
||
|
case ED_SPARSE:
|
||
|
_pdrmap = new DISTMAP( bnd.Distmap() ) ;
|
||
|
assert( _pdrmap->size() == bnd.Distmap().size() );
|
||
|
break;
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
BNDIST :: BNDIST ( const BNDIST & bnd )
|
||
|
:_edist(ED_NONE),
|
||
|
_pmvd(NULL),
|
||
|
_pdrmap(NULL)
|
||
|
{
|
||
|
(*this) = bnd;
|
||
|
|
||
|
LEAK_VAR_UPD(1)
|
||
|
}
|
||
|
|
||
|
bool BNDIST :: BChangeSubtype ( EDIST edist )
|
||
|
{
|
||
|
if ( BDenseType(edist) ^ BDense() )
|
||
|
return false;
|
||
|
_edist = edist;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void BNDIST :: Dump ()
|
||
|
{
|
||
|
if ( _pmvd )
|
||
|
{
|
||
|
cout << "\n\tDense version:";
|
||
|
DumpDense();
|
||
|
}
|
||
|
if ( _pdrmap )
|
||
|
{
|
||
|
cout << "\n\tSparse version:";
|
||
|
DumpSparse();
|
||
|
}
|
||
|
cout << "\n\n";
|
||
|
}
|
||
|
|
||
|
void BNDIST :: DumpSparse ()
|
||
|
{
|
||
|
assert( _pdrmap );
|
||
|
DISTMAP & dmap = *_pdrmap;
|
||
|
int i = 0;
|
||
|
for ( DISTMAP::iterator itdm = dmap.begin();
|
||
|
itdm != dmap.end();
|
||
|
++itdm, ++i )
|
||
|
{
|
||
|
const VIMD & vimd = (*itdm).first;
|
||
|
const VLREAL & vlr = (*itdm).second;
|
||
|
cout << "\n["
|
||
|
<< i
|
||
|
<< "] (";
|
||
|
dumpVimd(vimd);
|
||
|
cout << ")\t";
|
||
|
dumpVlr(vlr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void BNDIST :: DumpDense ()
|
||
|
{
|
||
|
assert( _pmvd );
|
||
|
dumpMdv( *_pmvd );
|
||
|
}
|
||
|
|
||
|
void BNDIST :: ConvertToDense ( const VIMD & vimd )
|
||
|
{
|
||
|
assert( _edist == ED_NONE || _edist == ED_SPARSE );
|
||
|
|
||
|
if ( _edist == ED_NONE )
|
||
|
{
|
||
|
assert( ! _pdrmap );
|
||
|
return;
|
||
|
}
|
||
|
// See if there is a sparse distribution to convert
|
||
|
if ( ! _pdrmap )
|
||
|
throw GMException( EC_DIST_MISUSE, "no prior sparse distribution to convert" );
|
||
|
|
||
|
int cParent = vimd.size() - 1;
|
||
|
int cState = vimd[cParent];
|
||
|
DISTMAP & dmap = *_pdrmap;
|
||
|
VIMD vimdMt; // Empty subscript array
|
||
|
VLREAL vlrDefault(cState); // Default value array
|
||
|
|
||
|
// First, try to find the default entry; use -1 if not found
|
||
|
DISTMAP::iterator itdm = dmap.find(vimdMt);
|
||
|
if ( itdm != dmap.end() )
|
||
|
vlrDefault = (*itdm).second;
|
||
|
else
|
||
|
vlrDefault = -1; // fill the array with -1.
|
||
|
|
||
|
assert( vlrDefault.size() == cState );
|
||
|
|
||
|
// Allocate the new dense m-d array
|
||
|
delete _pmvd;
|
||
|
_pmvd = new DISTDD( vimd );
|
||
|
DISTDD & mdv = *_pmvd;
|
||
|
// Fill each DPI with the appropriate default value
|
||
|
DISTDD::Iterator itmdv(mdv);
|
||
|
for ( int iState = 0; itmdv.BNext() ; iState++ )
|
||
|
{
|
||
|
itmdv.Next() = vlrDefault[ iState % cState ];
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now, iterate over the sparse array and store in the appropriate locations.
|
||
|
// Each entry in the sparse map is a complete state set for the target node.
|
||
|
// Since the child (target) node probabilities are the fastest varying subscript,
|
||
|
// each entry in sparse map is spread across "cState" entries in the dense map.
|
||
|
//
|
||
|
// Of course, this could be more efficient, but we're just testing for now.
|
||
|
//
|
||
|
VIMD vimdDense(vimd.size());
|
||
|
for ( itdm = dmap.begin(); itdm != dmap.end() ; ++itdm )
|
||
|
{
|
||
|
const VIMD & vimdSub = (*itdm).first;
|
||
|
VLREAL & vlrNext = (*itdm).second;
|
||
|
for ( int ip = 0 ; ip < cParent; ip++ )
|
||
|
{
|
||
|
vimdDense[ip] = vimdSub[ip];
|
||
|
}
|
||
|
for ( int ist = 0 ; ist < cState; ++ist )
|
||
|
{
|
||
|
vimdDense[cParent] = ist;
|
||
|
mdv[vimdDense] = vlrNext[ist];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Finally, nuke the old sparse distribution
|
||
|
delete _pdrmap;
|
||
|
_pdrmap = NULL;
|
||
|
// Set distribution type
|
||
|
_edist = ED_DENSE;
|
||
|
}
|
||
|
|
||
|
// Set distribution to "dense"
|
||
|
void BNDIST :: SetDense ( const VIMD & vimd )
|
||
|
{
|
||
|
Clear();
|
||
|
_vimdDim = vimd;
|
||
|
_pmvd = new DISTDD( vimd );
|
||
|
_edist = ED_DENSE;
|
||
|
}
|
||
|
|
||
|
// Set distribution to sparse
|
||
|
void BNDIST :: SetSparse ( const VIMD & vimd )
|
||
|
{
|
||
|
Clear();
|
||
|
_vimdDim = vimd;
|
||
|
_pdrmap = new DISTMAP;
|
||
|
_edist = ED_SPARSE;
|
||
|
}
|
||
|
|
||
|
// Return the "leak" or "default" vector from a sparse distribution
|
||
|
VLREAL * BNDIST :: PVlrLeak ()
|
||
|
{
|
||
|
assert( BSparse() );
|
||
|
const DISTMAP & dmap = Distmap();
|
||
|
const VIMD & vimdDim = VimdDim();
|
||
|
VIMD vimdLeak;
|
||
|
|
||
|
// First try to find the dimensionless "default" vector.
|
||
|
VLREAL * pvlrDefault = NULL;
|
||
|
DISTMAP::iterator itdm = dmap.find( vimdLeak );
|
||
|
if ( itdm != dmap.end() )
|
||
|
pvlrDefault = & (*itdm).second;
|
||
|
|
||
|
// Now try to find a specific zeroth vector; note that valarray<T>::resize
|
||
|
// stores all zeroes into the valarray by default. Also, skip the
|
||
|
// loweest dimension, since that's the size of each vector in the
|
||
|
// sparse map.
|
||
|
vimdLeak.resize( vimdDim.size() - 1 );
|
||
|
VLREAL * pvlrLeak = NULL;
|
||
|
itdm = dmap.find( vimdLeak );
|
||
|
if ( itdm != dmap.end() )
|
||
|
pvlrLeak = & (*itdm).second;
|
||
|
|
||
|
return pvlrLeak
|
||
|
? pvlrLeak
|
||
|
: pvlrDefault;
|
||
|
}
|
||
|
|
||
|
void BNDIST :: Clone ( const BNDIST & bndist )
|
||
|
{
|
||
|
ASSERT_THROW( _edist == ED_NONE,
|
||
|
EC_INVALID_CLONE,
|
||
|
"cannot clone into non-empty structure" );
|
||
|
self = bndist;
|
||
|
}
|