提交scripts
This commit is contained in:
1 parent
82caf72036
commit
07dabbd186
224 files changed
+130146
No files matched your search
@@ -0,0 +1,246 @@
|
||||
/******************************************************************
|
||||
Vladimir Kolmogorov, 2005
|
||||
vnk@microsoft.com
|
||||
|
||||
(c) Microsoft Corporation. All rights reserved.
|
||||
*******************************************************************/
|
||||
|
||||
#ifndef __MRFENERGY_H__
|
||||
#define __MRFENERGY_H__
|
||||
|
||||
#include "instances.h"
|
||||
|
||||
|
||||
// After MRFEnergy is allocated, there are two phases:
|
||||
// 1. Energy construction. Only AddNode(), AddNodeData() and AddEdge() may be called.
|
||||
//
|
||||
// Any call ZeroMessages(), SetAutomaticOrdering(), Minimize_TRW_S() or Minimize_BP()
|
||||
// completes graph construction; MRFEnergy goes to the second phase:
|
||||
// 2. Only functions AddNodeData(), ZeroMessages(), Minimize_TRW_S(), Minimize_BP()
|
||||
// or GetSolution() may be called. (The last function can be called only after
|
||||
// Minimize_TRW_S() or Minimize_BP()).
|
||||
|
||||
|
||||
template <class T> class MRFEnergy
|
||||
{
|
||||
private:
|
||||
struct Node;
|
||||
|
||||
public:
|
||||
typedef typename T::Label Label;
|
||||
typedef typename T::REAL REAL;
|
||||
typedef typename T::GlobalSize GlobalSize;
|
||||
typedef typename T::LocalSize LocalSize;
|
||||
typedef typename T::NodeData NodeData;
|
||||
typedef typename T::EdgeData EdgeData;
|
||||
|
||||
typedef Node* NodeId;
|
||||
typedef void (*ErrorFunction)(const char* msg);
|
||||
|
||||
// Constructor. Function errorFn is called with an error message, if an error occurs.
|
||||
MRFEnergy(GlobalSize Kglobal, ErrorFunction errorFn = NULL);
|
||||
|
||||
// Destructor.
|
||||
~MRFEnergy();
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Energy construction //
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// Adds a node with parameters K and data
|
||||
// (see the corresponding message*.h file for description).
|
||||
// Note: information in data is copied into internal memory.
|
||||
// Cannot be called after energy construction is completed.
|
||||
NodeId AddNode(LocalSize K, NodeData data);
|
||||
|
||||
// Modifies node parameter for existing node (namely, add information
|
||||
// in data to existing parameter). May be called at any time.
|
||||
// Node i must be NodeId returned by AddNode().
|
||||
void AddNodeData(NodeId i, NodeData data);
|
||||
|
||||
// Adds an edge between i and j. data determines edge parameters
|
||||
// (see the corresponding message*.h file for description).
|
||||
// Note: information in data is copied into internal memory.
|
||||
// Cannot be called after energy construction is completed.
|
||||
void AddEdge(NodeId i, NodeId j, EdgeData data);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Energy construction end //
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// Clears all messages. Completes energy construction (if not completed yet).
|
||||
void ZeroMessages();
|
||||
|
||||
// Adds to all message entries a value drawn uniformly from [min_value, max_value].
|
||||
// Normally, min_value can be set to 0 (except for TypeBinaryFast, in which case min_value = -max_value)
|
||||
void AddRandomMessages(unsigned int random_seed, REAL min_value, REAL max_value);
|
||||
|
||||
// The algorithm depends on the order of nodes.
|
||||
// By default nodes are processed in the order in which they were added.
|
||||
// The function below permutes this order using certain heuristics.
|
||||
// It may speed up the algorithm if, for example, the original order is random.
|
||||
//
|
||||
// Completes energy construction.
|
||||
// Cannot be called after energy construction is completed.
|
||||
void SetAutomaticOrdering();
|
||||
|
||||
// The structure below specifies (1) stopping criteria and
|
||||
// (2) how often to compute solution and print its energy.
|
||||
struct Options
|
||||
{
|
||||
Options()
|
||||
{
|
||||
// default parameters
|
||||
m_eps = -1; // not used
|
||||
m_iterMax = 1000000;
|
||||
m_printIter = 5; // After 10 iterations start printing the lower bound
|
||||
m_printMinIter = 10; // and the energy every 5 iterations.
|
||||
}
|
||||
|
||||
// stopping criterion
|
||||
REAL m_eps; // stop if the increase in the lower bound during one iteration is less or equal than m_eps.
|
||||
// Used only if m_eps >= 0, and only for TRW-S algorithm.
|
||||
int m_iterMax; // maximum number of iterations
|
||||
|
||||
// Option for printing lower bound and the energy.
|
||||
// Note: computing solution and its energy is slow
|
||||
// (it is comparable to the cost of one iteration).
|
||||
int m_printIter; // print lower bound and energy every m_printIter iterations
|
||||
int m_printMinIter; // do not print lower bound and energy before m_printMinIter iterations
|
||||
};
|
||||
|
||||
// Returns number of iterations. Sets lowerBound and energy.
|
||||
// If the user provides array min_marginals, then the code
|
||||
// sets this array accordingly. (The size of the array depends on the type
|
||||
// used. Normally, it's (# nodes)*(# labels). Exception: for TypeBinaryFast it's (# nodes).
|
||||
int Minimize_TRW_S(Options& options, REAL& lowerBound, REAL& energy, REAL* min_marginals = NULL);
|
||||
|
||||
// Returns number of iterations. Sets energy.
|
||||
int Minimize_BP(Options& options, REAL& energy, REAL* min_marginals = NULL);
|
||||
|
||||
// Returns an integer in [0,Ki). Can be called only after Minimize().
|
||||
Label GetSolution(NodeId i);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////
|
||||
// Implementation //
|
||||
//////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////
|
||||
private:
|
||||
|
||||
typedef typename T::Vector Vector;
|
||||
typedef typename T::Edge Edge;
|
||||
|
||||
struct MRFEdge;
|
||||
struct MallocBlock;
|
||||
|
||||
ErrorFunction m_errorFn;
|
||||
MallocBlock* m_mallocBlockFirst;
|
||||
Node* m_nodeFirst;
|
||||
Node* m_nodeLast;
|
||||
int m_nodeNum;
|
||||
int m_edgeNum;
|
||||
GlobalSize m_Kglobal;
|
||||
int m_vectorMaxSizeInBytes;
|
||||
|
||||
bool m_isEnergyConstructionCompleted;
|
||||
|
||||
char* m_buf; // buffer of size m_vectorMaxSizeInBytes
|
||||
// + max(m_vectorMaxSizeInBytes, Edge::GetBufSizeInBytes(m_vectorMaxSizeInBytes))
|
||||
|
||||
void CompleteGraphConstruction(); // nodes and edges cannot be added after calling this function
|
||||
void SetMonotonicTrees();
|
||||
|
||||
REAL ComputeSolutionAndEnergy(); // sets Node::m_solution, returns value of the energy
|
||||
|
||||
|
||||
|
||||
struct Node
|
||||
{
|
||||
int m_ordering; // unique integer in [0,m_nodeNum-1)
|
||||
|
||||
MRFEdge* m_firstForward; // first edge going to nodes with greater m_ordering
|
||||
MRFEdge* m_firstBackward; // first edge going to nodes with smaller m_ordering
|
||||
|
||||
Node* m_prev; // previous and next
|
||||
Node* m_next; // nodes according to m_ordering
|
||||
|
||||
Label m_solution; // integer in [0,m_D.m_K)
|
||||
LocalSize m_K; // local information about number of labels
|
||||
|
||||
Vector m_D; // must be the last member in the struct since its size is not fixed
|
||||
};
|
||||
|
||||
struct MRFEdge
|
||||
{
|
||||
MRFEdge* m_nextForward; // next forward edge with the same tail
|
||||
MRFEdge* m_nextBackward; // next backward edge with the same head
|
||||
Node* m_tail;
|
||||
Node* m_head;
|
||||
|
||||
REAL m_gammaForward; // = rho_{ij} / rho_{i} where i=m_tail, j=m_head
|
||||
REAL m_gammaBackward; // = rho_{ij} / rho_{j} where i=m_tail, j=m_head
|
||||
|
||||
Edge m_message; // must be the last member in the struct since its size is not fixed.
|
||||
// Stores edge information and either forward or backward message.
|
||||
// Most of the time it's the backward message; it gets replaced
|
||||
// by the forward message only temporarily inside Minimize_TRW_S() and Minimize_BP().
|
||||
};
|
||||
|
||||
// Use our own Malloc since
|
||||
// (a) new in C++ is slow and allocates minimum memory of 64 bytes (in Visual C++)
|
||||
// (b) we want simple (one function) deallocation instead of going through every allocated element
|
||||
struct MallocBlock
|
||||
{
|
||||
static const int minBlockSizeInBytes = 4096 - 3*sizeof(void*);
|
||||
MallocBlock* m_next;
|
||||
char* m_current; // first element of available memory in this block
|
||||
char* m_last; // first element outside of allocated memory for this block
|
||||
};
|
||||
char* Malloc(int bytesNum);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <class T> inline char* MRFEnergy<T>::Malloc(int bytesNum)
|
||||
{
|
||||
if (!m_mallocBlockFirst || m_mallocBlockFirst->m_current+bytesNum > m_mallocBlockFirst->m_last)
|
||||
{
|
||||
int size = (bytesNum > MallocBlock::minBlockSizeInBytes) ? bytesNum : MallocBlock::minBlockSizeInBytes;
|
||||
MallocBlock* b = (MallocBlock*) new char[sizeof(MallocBlock) + size];
|
||||
if (!b) m_errorFn("Not enough memory");
|
||||
b->m_current = (char*) b + sizeof(MallocBlock);
|
||||
b->m_last = b->m_current + size;
|
||||
|
||||
b->m_next = m_mallocBlockFirst;
|
||||
m_mallocBlockFirst = b;
|
||||
}
|
||||
|
||||
char* ptr = m_mallocBlockFirst->m_current;
|
||||
m_mallocBlockFirst->m_current += bytesNum;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class T> inline typename T::Label MRFEnergy<T>::GetSolution(NodeId i)
|
||||
{
|
||||
return i->m_solution;
|
||||
}
|
||||
|
||||
#include "MRFEnergy.inl"
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user