static void EigsOfSymMat( MAT& eigvecs, // out: one row per eigvec MAT& eigvals, // out: sorted const MAT& mat, // in: not modified bool fix_signs=true) // in: see FixEigSigns { CV_DbgAssert(IsSymmetric(mat, cv::trace(mat)[0] / double(1e16))); eigen(mat, eigvals, eigvecs); if (fix_signs) FixEigSigns(eigvecs); }
GenExpTLVec* CFGEnumeratorSingle::PopulateExpsOfGNCost(const GrammarNode* GN, uint32 Cost, bool Complete) { auto Retval = new GenExpTLVec(); GNCostPair Key(GN, Cost); Done = false; auto Type = GN->GetType(); PushExpansion(GN->ToString()); auto const ExpansionTypeID = GetExpansionTypeID(); auto FPVar = GN->As<GrammarFPVar>(); // The base cases if (FPVar != nullptr) { return MakeBaseExpression<GenFPExpression>(Retval, FPVar->GetOp(), Type, ExpansionTypeID, Cost, Key, Complete); } auto LetVar = GN->As<GrammarLetVar>(); if (LetVar != nullptr) { return MakeBaseExpression<GenLetVarExpression>(Retval, LetVar->GetOp(), Type, ExpansionTypeID, Cost, Key, Complete); } auto Const = GN->As<GrammarConst>(); if (Const != nullptr) { return MakeBaseExpression<GenConstExpression>(Retval, Const->GetOp(), Type, ExpansionTypeID, Cost, Key, Complete); } auto Func = GN->As<GrammarFunc>(); if (Func != nullptr) { auto const& Args = Func->GetChildren(); auto Op = Func->GetOp(); const uint32 OpCost = Op->GetCost(); const uint32 Arity = Op->GetArity(); if (Cost < Arity + OpCost) { Retval->Freeze(); ExpRepository[Key] = Retval; PopExpansion(); return Retval; } PartitionGenerator* PG; if (Op->IsSymmetric() && Args[0] == Args[1]) { PG = new SymPartitionGenerator(Cost - OpCost); } else { PG = new PartitionGenerator(Cost - OpCost, Arity); } const uint32 NumPartitions = PG->Size(); for (uint32 i = 0; i < NumPartitions; ++i) { auto Feasible = true; vector<const GenExpTLVec*> ArgExpVecs(Arity, nullptr); auto CurPartition = (*PG)[i]; vector<GenExpTLVec::ConstIterator> Begins(Arity); vector<GenExpTLVec::ConstIterator> Ends(Arity); for (uint32 j = 0; j < Arity; ++j) { auto CurVec = GetVecForGNCost(Args[j], CurPartition[j]); if (CurVec == nullptr) { CurVec = PopulateExpsOfGNCost(Args[j], CurPartition[j], false); } if (CurVec->Size() == 0) { Feasible = false; break; } else { ArgExpVecs[j] = CurVec; Begins[j] = CurVec->Begin(); Ends[j] = CurVec->End(); } } if (!Feasible) { continue; } // Iterate over the cross product auto CPGen = new CrossProductGenerator(Begins, Ends, GetPoolForSize(Arity)); for (auto CurArgs = CPGen->GetNext(); CurArgs != nullptr; CurArgs = CPGen->GetNext()) { auto CurExp = new (FuncExpPool->malloc()) GenFuncExpression(static_cast<const InterpretedFuncOperator*>(Op), CurArgs); auto Status = (Complete ? Solver->ExpressionCallBack(CurExp, Type, ExpansionTypeID, Index) : Solver->SubExpressionCallBack(CurExp, Type, ExpansionTypeID)); if ((Status & DELETE_EXPRESSION) == 0) { CPGen->RelinquishOwnerShip(); Retval->PushBack(CurExp); NumExpsCached++; } else { FuncExpPool->free(CurExp); } if ((Status & STOP_ENUMERATION) != 0) { Done = true; break; } } delete CPGen; if (Done) { break; } } delete PG; Retval->Freeze(); ExpRepository[Key] = Retval; PopExpansion(); return Retval; } auto Let = GN->As<GrammarLet>(); // We handle this in similar spirit as functions if (Let != nullptr) { auto const& Bindings = Let->GetBindings(); const uint32 NumBindings = Bindings.size(); const uint32 Arity = NumBindings + 1; auto BoundNode = Let->GetBoundExpression(); const uint32 NumLetBoundVars = TheGrammar->GetNumLetBoundVars(); if (Cost < Arity + 1) { Retval->Freeze(); ExpRepository[Key] = Retval; PopExpansion(); return Retval; } // Making a let binding incurs a cost of 1! auto PG = new PartitionGenerator(Cost - 1, Arity); const uint32 NumPartitions = PG->Size(); for (uint32 i = 0; i < NumPartitions; ++i) { auto Feasible = true; vector<const GenExpTLVec*> ArgExpVecs(Arity, nullptr); auto CurPartition = (*PG)[i]; vector<GenExpTLVec::ConstIterator> Begins(Arity); vector<GenExpTLVec::ConstIterator> Ends(Arity); uint32 j = 0; uint32* Positions = new uint32[NumBindings]; for (auto it = Bindings.begin(); it != Bindings.end(); ++it) { auto CurVec = GetVecForGNCost(it->second, CurPartition[j]); if (CurVec == nullptr) { CurVec = PopulateExpsOfGNCost(it->second, CurPartition[j], false); } if (CurVec->Size() == 0) { Feasible = false; break; } else { ArgExpVecs[j] = CurVec; Begins[j] = CurVec->Begin(); Ends[j] = CurVec->End(); } Positions[j] = it->first->GetOp()->GetPosition(); ++j; } if (!Feasible) { delete[] Positions; continue; } // Finally, the expression set for the bound expression auto BoundVec = GetVecForGNCost(BoundNode, CurPartition[j]); if (BoundVec == nullptr) { BoundVec = PopulateExpsOfGNCost(BoundNode, CurPartition[j], false); } if (BoundVec->Size() == 0) { // cross product is empty not feasible delete[] Positions; continue; } else { ArgExpVecs[NumBindings] = BoundVec; Begins[NumBindings] = BoundVec->Begin(); Ends[NumBindings] = BoundVec->End(); } // Iterate over the cross product of expressions // The bindings object will be of size of the NUMBER // of let bound vars for the whole grammar auto CPGen = new CrossProductGenerator(Begins, Ends, GetPoolForSize(Arity)); GenExpressionBase const** BindVec = nullptr; auto BindVecPool = GetPoolForSize(NumLetBoundVars); for (auto CurArgs = CPGen->GetNext(); CurArgs != nullptr; CurArgs = CPGen->GetNext()) { // We need to build the binding vector based on the position if (BindVec == nullptr) { BindVec = (GenExpressionBase const**)BindVecPool->malloc(); memset(BindVec, 0, sizeof(GenExpressionBase const*) * NumLetBoundVars); } for (uint32 k = 0; k < NumBindings; ++k) { BindVec[Positions[k]] = CurArgs[k]; } auto CurExp = new (LetExpPool->malloc()) GenLetExpression(BindVec, CurArgs[NumBindings], NumLetBoundVars); auto Status = (Complete ? Solver->ExpressionCallBack(CurExp, Type, ExpansionTypeID, Index) : Solver->SubExpressionCallBack(CurExp, Type, ExpansionTypeID)); if ((Status & DELETE_EXPRESSION) == 0) { BindVec = nullptr; Retval->PushBack(CurExp); NumExpsCached++; } else { LetExpPool->free(CurExp); } if ((Status & STOP_ENUMERATION) != 0) { Done = true; break; } } delete CPGen; delete[] Positions; if (Done) { break; } } delete PG; Retval->Freeze(); ExpRepository[Key] = Retval; PopExpansion(); return Retval; } auto NT = GN->As<GrammarNonTerminal>(); if (NT != nullptr) { const vector<GrammarNode*>& Expansions = TheGrammar->GetExpansions(NT); for (auto const& Expansion : Expansions) { auto CurVec = GetVecForGNCost(Expansion, Cost); if (CurVec == nullptr) { CurVec = PopulateExpsOfGNCost(Expansion, Cost, Complete); } Retval->Merge(*CurVec); if (Done) { break; } } Retval->Freeze(); ExpRepository[Key] = Retval; PopExpansion(); return Retval; } // Should NEVER get here throw InternalError((string)"You probably subclassed GrammarNode and forgot to change " + "CFGEnumerator.cpp.\nAt: " + __FILE__ + ":" + to_string(__LINE__)); }
inline void NestedDissectionRecursion ( const Graph& graph, const vector<Int>& perm, Separator& sep, NodeInfo& node, Int off, const BisectCtrl& ctrl ) { DEBUG_CSE const Int numSources = graph.NumSources(); const Int* offsetBuf = graph.LockedOffsetBuffer(); const Int* sourceBuf = graph.LockedSourceBuffer(); const Int* targetBuf = graph.LockedTargetBuffer(); if( numSources <= ctrl.cutoff ) { // Filter out the graph of the diagonal block Int numValidEdges = 0; const Int numEdges = graph.NumEdges(); for( Int e=0; e<numEdges; ++e ) if( targetBuf[e] < numSources ) ++numValidEdges; vector<Int> subOffsets(numSources+1), subTargets(Max(numValidEdges,1)); Int sourceOff = 0; Int validCounter = 0; Int prevSource = -1; for( Int e=0; e<numEdges; ++e ) { const Int source = sourceBuf[e]; const Int target = targetBuf[e]; while( source != prevSource ) { subOffsets[sourceOff++] = validCounter; ++prevSource; } if( target < numSources ) subTargets[validCounter++] = target; } while( sourceOff <= numSources ) { subOffsets[sourceOff++] = validCounter; } // Technically, SuiteSparse expects column-major storage, but since // the matrix is structurally symmetric, it's okay to pass in the // row-major representation vector<Int> amdPerm; AMDOrder( subOffsets, subTargets, amdPerm ); // Compute the symbolic factorization of this leaf node using the // reordering just computed node.LOffsets.resize( numSources+1 ); node.LParents.resize( numSources ); vector<Int> LNnz( numSources ), Flag( numSources ), amdPermInv( numSources ); suite_sparse::ldl::Symbolic ( numSources, subOffsets.data(), subTargets.data(), node.LOffsets.data(), node.LParents.data(), LNnz.data(), Flag.data(), amdPerm.data(), amdPermInv.data() ); // Fill in this node of the local separator tree sep.off = off; sep.inds.resize( numSources ); for( Int i=0; i<numSources; ++i ) sep.inds[i] = perm[amdPerm[i]]; // TODO: Replace with better deletion mechanism SwapClear( sep.children ); // Fill in this node of the local elimination tree node.size = numSources; node.off = off; // TODO: Replace with better deletion mechanism SwapClear( node.children ); set<Int> lowerStruct; for( Int s=0; s<node.size; ++s ) { const Int edgeOff = offsetBuf[s]; const Int numConn = offsetBuf[s+1] - edgeOff; for( Int t=0; t<numConn; ++t ) { const Int target = targetBuf[edgeOff+t]; if( target >= numSources ) lowerStruct.insert( off+target ); } } CopySTL( lowerStruct, node.origLowerStruct ); } else { DEBUG_ONLY( if( !IsSymmetric(graph) ) { Print( graph, "graph" ); LogicError("Graph was not symmetric"); } ) // Partition the graph and construct the inverse map Graph leftChild, rightChild; vector<Int> map; const Int sepSize = Bisect( graph, leftChild, rightChild, map, ctrl ); vector<Int> invMap( numSources ); for( Int s=0; s<numSources; ++s ) invMap[map[s]] = s; DEBUG_ONLY( if( !IsSymmetric(leftChild) ) { Print( graph, "graph" ); Print( leftChild, "leftChild" ); LogicError("Left child was not symmetric"); } )
bool Eigendecomposition(const Matrix4& A,Vector4& lambda,Matrix4& Q) { if(!IsSymmetric(A)) return false; Matrix4 U; return SVD(A,U,lambda,Q); }