template <class T> void MRFEnergy<T>::AddRandomMessages(unsigned int random_seed, REAL min_value, REAL max_value) { Node* i; MRFEdge* e; int k; if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } srand(random_seed); for (i=m_nodeFirst; i; i=i->m_next) { for (e=i->m_firstForward; e; e=e->m_nextForward) { Vector* M = e->m_message.GetMessagePtr(); for (k=0; k<M->GetArraySize(m_Kglobal, i->m_K); k++) { REAL x = (REAL)( min_value + rand()/((double)RAND_MAX) * (max_value - min_value) ); x += M->GetArrayValue(m_Kglobal, i->m_K, k); M->SetArrayValue(m_Kglobal, i->m_K, k, x); } } } }
template <class T> void MRFEnergy<T>::ZeroMessages() { Node* i; MRFEdge* e; if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } for (i=m_nodeFirst; i; i=i->m_next) { for (e=i->m_firstForward; e; e=e->m_nextForward) { e->m_message.GetMessagePtr()->SetZero(m_Kglobal, i->m_K); } } }
template <class T> void MRFEnergy<T>::SetMonotonicTrees() { Node* i; MRFEdge* e; if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } for (i=m_nodeFirst; i; i=i->m_next) { REAL mu; int nForward = 0, nBackward = 0; for (e=i->m_firstForward; e; e=e->m_nextForward) { nForward ++; } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { nBackward ++; } int ni = (nForward > nBackward) ? nForward : nBackward; mu = (REAL)1 / ni; for (e=i->m_firstBackward; e; e=e->m_nextBackward) { e->m_gammaBackward = mu; } for (e=i->m_firstForward; e; e=e->m_nextForward) { e->m_gammaForward = mu; } } }
template <class T> int MRFEnergy<T>::Minimize_TRW_S(Options& options, std::vector<REAL> &lowerBound_arr, std::vector<REAL> &energy_arr, std::vector<clock_t> &time_arr, REAL* min_marginals) { Node* i; Node* j; MRFEdge* e; REAL vMin; int iter; REAL lowerBoundPrev; clock_t tStart = clock(); if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } printf("TRW_S algorithm\n"); SetMonotonicTrees(); Vector* Di = (Vector*) m_buf; void* buf = (void*) (m_buf + m_vectorMaxSizeInBytes); iter = 0; bool lastIter = false; // main loop for (iter=1; ; iter++) { if (iter >= options.m_iterMax) lastIter = true; //////////////////////////////////////////////// // forward pass // //////////////////////////////////////////////// REAL* min_marginals_ptr = min_marginals; for (i=m_nodeFirst; i; i=i->m_next) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // normalize Di, update lower bound // vMin = Di->ComputeAndSubtractMin(m_Kglobal, i->m_K); // do not compute lower bound // lowerBound += vMin; // during the forward pass // pass messages from i to nodes with higher m_ordering for (e=i->m_firstForward; e; e=e->m_nextForward) { assert(e->m_tail == i); j = e->m_head; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, e->m_gammaForward, 0, buf); // lowerBound += vMin; // do not compute lower bound during the forward pass } if (lastIter && min_marginals) { min_marginals_ptr += Di->GetArraySize(m_Kglobal, i->m_K); } } //////////////////////////////////////////////// // backward pass // //////////////////////////////////////////////// REAL lowerBound = 0; for (i=m_nodeLast; i; i=i->m_prev) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // normalize Di, update lower bound vMin = Di->ComputeAndSubtractMin(m_Kglobal, i->m_K); lowerBound += vMin; // pass messages from i to nodes with smaller m_ordering for (e=i->m_firstBackward; e; e=e->m_nextBackward) { assert(e->m_head == i); j = e->m_tail; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, e->m_gammaBackward, 1, buf); lowerBound += vMin; } if (lastIter && min_marginals) { min_marginals_ptr -= Di->GetArraySize(m_Kglobal, i->m_K); for (int k=0; k<Di->GetArraySize(m_Kglobal, i->m_K); k++) { min_marginals_ptr[k] = Di->GetArrayValue(m_Kglobal, i->m_K, k); } } } //////////////////////////////////////////////// // check stopping criterion // //////////////////////////////////////////////// // Add lower bound, energy and time to output array lowerBound_arr.push_back(lowerBound); energy_arr.push_back(ComputeSolutionAndEnergy()); time_arr.push_back((clock() - tStart) * 1.0 / CLOCKS_PER_SEC); // print lower bound and energy, if necessary if ( lastIter || ( iter>=options.m_printMinIter && (options.m_printIter<1 || iter%options.m_printIter==0) ) ) { REAL energy = ComputeSolutionAndEnergy(); printf("iter %d: lower bound = %f, energy = %f\n", iter, lowerBound, energy); } if (lastIter) break; // check convergence of lower bound if (options.m_eps >= 0) { if (iter > 1 && lowerBound - lowerBoundPrev <= options.m_eps) { lastIter = true; } lowerBoundPrev = lowerBound; } } return iter; }
template <class T> int MRFEnergy<T>::Minimize_BP(Options& options, std::vector<REAL> &energy_arr, std::vector<clock_t> &time_arr, REAL* min_marginals) { Node* i; Node* j; MRFEdge* e; REAL vMin; int iter; clock_t tStart = clock(); if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } printf("BP algorithm\n"); Vector* Di = (Vector*) m_buf; void* buf = (void*) (m_buf + m_vectorMaxSizeInBytes); iter = 0; bool lastIter = false; // main loop for (iter=1; ; iter++) { if (iter >= options.m_iterMax) lastIter = true; //////////////////////////////////////////////// // forward pass // //////////////////////////////////////////////// REAL* min_marginals_ptr = min_marginals; for (i=m_nodeFirst; i; i=i->m_next) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // pass messages from i to nodes with higher m_ordering for (e=i->m_firstForward; e; e=e->m_nextForward) { assert(i == e->m_tail); j = e->m_head; const REAL gamma = 1; e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, gamma, 0, buf); } if (lastIter && min_marginals) { min_marginals_ptr += Di->GetArraySize(m_Kglobal, i->m_K); } } //////////////////////////////////////////////// // backward pass // //////////////////////////////////////////////// for (i=m_nodeLast; i; i=i->m_prev) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // pass messages from i to nodes with smaller m_ordering for (e=i->m_firstBackward; e; e=e->m_nextBackward) { assert(i == e->m_head); j = e->m_tail; const REAL gamma = 1; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, gamma, 1, buf); } if (lastIter && min_marginals) { min_marginals_ptr -= Di->GetArraySize(m_Kglobal, i->m_K); for (int k=0; k<Di->GetArraySize(m_Kglobal, i->m_K); k++) { min_marginals_ptr[k] = Di->GetArrayValue(m_Kglobal, i->m_K, k); } } } //////////////////////////////////////////////// // check stopping criterion // //////////////////////////////////////////////// // Add energy and time to output array energy_arr.push_back(ComputeSolutionAndEnergy()); time_arr.push_back((clock() - tStart) * 1.0 / CLOCKS_PER_SEC); // print energy, if necessary if ( lastIter || ( iter>=options.m_printMinIter && (options.m_printIter<1 || iter%options.m_printIter==0) ) ) { REAL energy = ComputeSolutionAndEnergy(); printf("iter %d: energy = %f\n", iter, energy); } // if finishFlag==true terminate if (lastIter) break; } return iter; }
template <class T> void MRFEnergy<T>::SetAutomaticOrdering() { int dMin; Node* i; Node* iMin; Node* list; Node* listBoundary; MRFEdge* e; if (m_isEnergyConstructionCompleted) { m_errorFn("Error in SetAutomaticOrdering(): function cannot be called after graph construction is completed"); } printf("Setting automatic ordering... "); list = m_nodeFirst; listBoundary = NULL; m_nodeFirst = m_nodeLast = NULL; for (i=list; i; i=i->m_next) { i->m_ordering = 2*m_nodeNum; // will contain remaining degree mod m_nodeNum (i.e. number of edges connecting to nodes in 'listBoundary' and 'list') // if i->m_ordering \in [2*m_nodeNum; 3*m_nodeNum) - not assigned yet, belongs to 'list' // if i->m_ordering \in [m_nodeNum; 2*m_nodeNum) - not assigned yet, belongs to 'listBoundary' // if i->m_ordering \in [0; m_nodeNum ) - assigned, belongs to 'm_nodeFirst' for (e=i->m_firstForward; e; e=e->m_nextForward) { i->m_ordering ++; } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { i->m_ordering ++; } } while (list) { // find node with the smallest remaining degree in list dMin = m_nodeNum; for (i=list; i; i=i->m_next) { assert(i->m_ordering >= 2*m_nodeNum); if (dMin > i->m_ordering - 2*m_nodeNum) { dMin = i->m_ordering - 2*m_nodeNum; iMin = i; } } i = iMin; // remove i from list if (i->m_prev) i->m_prev->m_next = i->m_next; else list = i->m_next; if (i->m_next) i->m_next->m_prev = i->m_prev; // add i to listBoundary listBoundary = i; i->m_prev = NULL; i->m_next = NULL; i->m_ordering -= m_nodeNum; while (listBoundary) { // find node with the smallest remaining degree in listBoundary dMin = m_nodeNum; for (i=listBoundary; i; i=i->m_next) { assert(i->m_ordering >= m_nodeNum && i->m_ordering < 2*m_nodeNum); if (dMin > i->m_ordering - m_nodeNum) { dMin = i->m_ordering - m_nodeNum; iMin = i; } } i = iMin; // remove i from listBoundary if (i->m_prev) i->m_prev->m_next = i->m_next; else listBoundary = i->m_next; if (i->m_next) i->m_next->m_prev = i->m_prev; // add i to m_nodeFirst if (m_nodeLast) { m_nodeLast->m_next = i; i->m_ordering = m_nodeLast->m_ordering + 1; } else { m_nodeFirst = i; i->m_ordering = 0; } i->m_prev = m_nodeLast; m_nodeLast = i; i->m_next = NULL; // process neighbors of i=m_nodeLast: decrease their remaining degree, // put them into listBoundary (if they are in list) for (e=m_nodeLast->m_firstForward; e; e=e->m_nextForward) { assert(m_nodeLast == e->m_tail); i = e->m_head; if (i->m_ordering >= m_nodeNum) { i->m_ordering --; // decrease remaining degree of i if (i->m_ordering >= 2*m_nodeNum) { // remove i from list if (i->m_prev) i->m_prev->m_next = i->m_next; else list = i->m_next; if (i->m_next) i->m_next->m_prev = i->m_prev; // add i to listBoundary if (listBoundary) listBoundary->m_prev = i; i->m_prev = NULL; i->m_next = listBoundary; listBoundary = i; i->m_ordering -= m_nodeNum; } } } for (e=m_nodeLast->m_firstBackward; e; e=e->m_nextBackward) { assert(m_nodeLast == e->m_head); i = e->m_tail; if (i->m_ordering >= m_nodeNum) { i->m_ordering --; // decrease remaining degree of i if (i->m_ordering >= 2*m_nodeNum) { // remove i from list if (i->m_prev) i->m_prev->m_next = i->m_next; else list = i->m_next; if (i->m_next) i->m_next->m_prev = i->m_prev; // add i to listBoundary if (listBoundary) listBoundary->m_prev = i; i->m_prev = NULL; i->m_next = listBoundary; listBoundary = i; i->m_ordering -= m_nodeNum; } } } } } printf("done\n"); CompleteGraphConstruction(); }
template <class T> int MRFEnergy<T>::Minimize_BP(Options& options, REAL& energy, REAL* min_marginals) { Node* i; Node* j; MRFEdge* e; REAL vMin; int iter; if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } if (verbosityLevel >= 1) printf("BP algorithm\n"); Vector* Di = (Vector*) m_buf; void* buf = (void*) (m_buf + m_vectorMaxSizeInBytes); iter = 0; bool lastIter = false; //init time measurements: Anton timePlot.resize(options.m_iterMax, -1); lbPlot.resize(options.m_iterMax, -1); ePlot.resize(options.m_iterMax, -1); clock_t tStart = clock(); // main loop for (iter=1; ; iter++) { if (iter >= options.m_iterMax) lastIter = true; //////////////////////////////////////////////// // forward pass // //////////////////////////////////////////////// REAL* min_marginals_ptr = min_marginals; for (i=m_nodeFirst; i; i=i->m_next) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // pass messages from i to nodes with higher m_ordering for (e=i->m_firstForward; e; e=e->m_nextForward) { assert(i == e->m_tail); j = e->m_head; const REAL gamma = 1; e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, gamma, 0, buf); } if (lastIter && min_marginals) { min_marginals_ptr += Di->GetArraySize(m_Kglobal, i->m_K); } } //////////////////////////////////////////////// // backward pass // //////////////////////////////////////////////// for (i=m_nodeLast; i; i=i->m_prev) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // pass messages from i to nodes with smaller m_ordering for (e=i->m_firstBackward; e; e=e->m_nextBackward) { assert(i == e->m_head); j = e->m_tail; const REAL gamma = 1; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, gamma, 1, buf); } if (lastIter && min_marginals) { min_marginals_ptr -= Di->GetArraySize(m_Kglobal, i->m_K); for (int k=0; k<Di->GetArraySize(m_Kglobal, i->m_K); k++) { min_marginals_ptr[k] = Di->GetArrayValue(m_Kglobal, i->m_K, k); } } } //////////////////////////////////////////////// // check stopping criterion // //////////////////////////////////////////////// //update time measurements: Anton timePlot[iter - 1] = (double)(clock() - tStart) / CLOCKS_PER_SEC; lbPlot[iter - 1] = std::numeric_limits<double>::signaling_NaN(); ePlot[iter - 1] = ComputeSolutionAndEnergy(); // print energy, if necessary if ( lastIter || ( iter>=options.m_printMinIter && (options.m_printIter<1 || iter%options.m_printIter==0) ) ) { //energy = ComputeSolutionAndEnergy(); energy = ePlot[iter - 1]; //Anton if( (verbosityLevel == 2) || (lastIter && (verbosityLevel == 1)) ) printf("iter %d: energy = %f\n", iter, energy); } // if finishFlag==true terminate if (lastIter) break; } return iter; }
template <class T> int MRFEnergy<T>::Minimize_TRW_S(Options& options, REAL& lowerBound, REAL& energy) { Node* i; Node* j; MRFEdge* e; REAL vMin; int iter; REAL lowerBoundPrev; if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } SetMonotonicTrees(); Vector* Di = (Vector*) m_buf; void* buf = (void*) (m_buf + m_vectorMaxSizeInBytes); iter = 0; // main loop for (iter=1; ; iter++) { //////////////////////////////////////////////// // forward pass // //////////////////////////////////////////////// for (i=m_nodeFirst; i; i=i->m_next) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // normalize Di, update lower bound // vMin = Di->ComputeAndSubtractMin(m_Kglobal, i->m_K); // do not compute lower bound // lowerBound += vMin; // during the forward pass // pass messages from i to nodes with higher m_ordering for (e=i->m_firstForward; e; e=e->m_nextForward) { assert(e->m_tail == i); j = e->m_head; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, e->m_gammaForward, 0, buf); // lowerBound += vMin; // do not compute lower bound during the forward pass } } //////////////////////////////////////////////// // backward pass // //////////////////////////////////////////////// lowerBound = 0; for (i=m_nodeLast; i; i=i->m_prev) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // normalize Di, update lower bound vMin = Di->ComputeAndSubtractMin(m_Kglobal, i->m_K); lowerBound += vMin; // pass messages from i to nodes with smaller m_ordering for (e=i->m_firstBackward; e; e=e->m_nextBackward) { assert(e->m_head == i); j = e->m_tail; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, e->m_gammaBackward, 1, buf); lowerBound += vMin; } } //////////////////////////////////////////////// // check stopping criterion // //////////////////////////////////////////////// bool finishFlag = false; if (iter >= options.m_iterMax) finishFlag = true; energy = ComputeSolutionAndEnergy(); REAL rel_gap = (energy - lowerBound)/energy; if (options.m_printMinIter) { mexPrintf("iter: %d ", iter); if (std::isinf(energy)) mexPrintf("lower bound: %g, inconsistent solution. \n", lowerBound); else mexPrintf("energy: %g lower bound: %g rel_gap: %g \n", energy, lowerBound, rel_gap); mexEvalString("drawnow"); } if (rel_gap < options.m_relgapMax) finishFlag = true; // if finishFlag==true terminate if (finishFlag) break; } return iter; }
template <class T> int MRFEnergy<T>::Minimize_BP(Options& options, REAL& energy) { Node* i; Node* j; MRFEdge* e; REAL vMin; int iter; if (!m_isEnergyConstructionCompleted) { CompleteGraphConstruction(); } Vector* Di = (Vector*) m_buf; void* buf = (void*) (m_buf + m_vectorMaxSizeInBytes); iter = 0; // main loop for (iter=1; ; iter++) { //////////////////////////////////////////////// // forward pass // //////////////////////////////////////////////// for (i=m_nodeFirst; i; i=i->m_next) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // pass messages from i to nodes with higher m_ordering for (e=i->m_firstForward; e; e=e->m_nextForward) { assert(i == e->m_tail); j = e->m_head; const REAL gamma = 1; e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, gamma, 0, buf); } } //////////////////////////////////////////////// // backward pass // //////////////////////////////////////////////// for (i=m_nodeLast; i; i=i->m_prev) { Di->Copy(m_Kglobal, i->m_K, &i->m_D); for (e=i->m_firstBackward; e; e=e->m_nextBackward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } for (e=i->m_firstForward; e; e=e->m_nextForward) { Di->Add(m_Kglobal, i->m_K, e->m_message.GetMessagePtr()); } // pass messages from i to nodes with smaller m_ordering for (e=i->m_firstBackward; e; e=e->m_nextBackward) { assert(i == e->m_head); j = e->m_tail; const REAL gamma = 1; vMin = e->m_message.UpdateMessage(m_Kglobal, i->m_K, j->m_K, Di, gamma, 1, buf); } } //////////////////////////////////////////////// // check stopping criterion // //////////////////////////////////////////////// bool finishFlag = false; if (iter >= options.m_iterMax) { finishFlag = true; } // if finishFlag==true terminate if (finishFlag) { break; } } return iter; }