Assignments CorrespondenceGenerator::generateGroupAssignments() { Assignments generatedAssignments; auto & segsA = sA->property["segments"].value<Segments>(); auto & segsB = sB->property["segments"].value<Segments>(); auto boxA = sA->bbox(), boxB = sB->bbox(); auto & groupsA = sA->property["groups"].value< std::vector< std::vector<size_t> > >(); auto & groupsB = sB->property["groups"].value< std::vector< std::vector<size_t> > >(); /// Build similarity matrix of groups: Eigen::MatrixXd similiarity = Eigen::MatrixXd::Ones( groupsA.size(), groupsB.size() + 1 ); for(size_t i = 0; i < similiarity.rows(); i++){ double minVal = DBL_MAX; for(size_t j = 0; j < similiarity.cols(); j++){ double val = 0; if( j < groupsB.size() ) { Eigen::AlignedBox3d groupBoxA, groupBoxB; for(auto sid : groupsA[i]) groupBoxA.extend( segsA[sid].property["bbox"].value<Eigen::AlignedBox3d>() ); for(auto sid : groupsB[j]) groupBoxB.extend( segsB[sid].property["bbox"].value<Eigen::AlignedBox3d>() ); Vector3 relativeCenterA = (groupBoxA.center()-boxA.min()).array() / boxA.sizes().array(); Vector3 relativeCenterB = (groupBoxB.center()-boxB.min()).array() / boxB.sizes().array(); val = ( relativeCenterA - relativeCenterB ).norm(); minVal = std::min(minVal, val); } similiarity(i,j) = val; } double maxVal = similiarity.row(i).maxCoeff(); if(maxVal == 0) maxVal = 1.0; for(size_t j = 0; j < groupsB.size(); j++) similiarity(i,j) = (similiarity(i,j) - minVal) / maxVal; } std::vector< std::vector<float> > data; for(int i = 0; i < similiarity.rows(); i++){ std::vector<float> dataRow; for(int j = 0; j < similiarity.cols(); j++) dataRow.push_back( similiarity(i,j) ); data.push_back(dataRow); } if(false) showTableColorMap(data, true); // DEBUG // Parameters: double similarity_threshold = 0.25; int count_threshold = 1; // Collect good candidates Assignments candidates; for(size_t i = 0; i < similiarity.rows(); i++){ QVector<size_t> candidate; for(size_t j = 0; j < similiarity.cols(); j++){ if(similiarity(i,j) < similarity_threshold) candidate << j; } candidates << candidate; } Assignments assignments; cart_product(assignments, candidates); // Filter assignments Assignments filtered; for(auto & a : assignments) { QMap<size_t,size_t> counts; bool accept = true; auto NOTHING_SEGMENT = similiarity.cols()-1; for(auto i : a) counts[i]++; for(auto k : counts.keys()){ if(k != NOTHING_SEGMENT && counts[k] > count_threshold){ accept = false; break; } } if( accept ) filtered << a; } // DEBUG: if(true) saveToTextFile("assignments.txt", vecToString2(filtered)); generatedAssignments = filtered; return generatedAssignments; }
//MAIN LOGIC BEGINS int main() { //first unsigned int=total length of the actual representation, char = first 8 digits of the actual representation, //each KeyObject has these properties: //unsigned int unencodedLength; the total length of the unencoded number //unsigned int firstNDigits; the first 32 digits of the unencoded number //unsigned int primeRepresentation; the encoded representation of the number/key std::vector<KeyObject> keys; for(unsigned int i=0; i < 10000; i++){ keys.push_back(KeyObject()); } //unsigned int initialLowerBoundIndex = 0; //recursiveFillKeys(lowerBounds,upperBounds,initialLowerBoundIndex,keys,primes); //simple examle of generating the keys structure. (these are the numbers we will reduce the file to, //we store them in our ultra compact representation with some identifying info) //for (unsigned int i=6; i<10; i++){ // for (unsigned int j=6; j<10; j++){ // keys[(h-6)*16 + (i-6)*4 + (j-6)] = unsigned integerExponent(prime[0],i)*unsigned integerExponent(prime[1],j).... // } //} Vvi input(build_input()); std::cout << input << "\n"; Vvi output; cart_product(input, output); std::cout << output << "\n"; //sample input/output //input // ( // (0, 1, 2, ) // (10, 11, 12, ) // (20, 21, 22, ) // ) // output // ( // (0, 10, 20, ) // (1, 10, 20, ) // (2, 10, 20, ) // (0, 11, 20, ) // (1, 11, 20, ) // (2, 11, 20, ) // (0, 12, 20, ) // (1, 12, 20, ) // (2, 12, 20, ) // (0, 10, 21, ) // (1, 10, 21, ) // (2, 10, 21, ) // (0, 11, 21, ) // (1, 11, 21, ) // (2, 11, 21, ) // (0, 12, 21, ) // (1, 12, 21, ) // (2, 12, 21, ) // (0, 10, 22, ) // (1, 10, 22, ) // (2, 10, 22, ) // (0, 11, 22, ) // (1, 11, 22, ) // (2, 11, 22, ) // (0, 12, 22, ) // (1, 12, 22, ) // (2, 12, 22, )) unsigned int counter = 0; for(Vvi::iterator it = output.begin(); ; ) { //keyExponentValues gives us a vector with all the exponents we need to use //to create a key //here we calculate the number represented by the exponents mpz_t n; mpz_init(n); mpz_set(n,1); for (Vi::iterator keyExponentValues = it->begin(); ; ){ mpz_t k; mpz_init(k); mpz_set(k,globals.primes[counter]); mpz_mul(n,n,k); n *= k; mpz_clear (k); //mpz_sizeinbase (mpz_t op, int base) //mpz_sizeinbase (mpz_t op, int base) //base can only be up to size 62 max! //here we store the length of the number represented by the exponents keys[counter].unencodedLength = 0; //here we store the first n digits of the number represented by the exponents keys[counter].firstNDigits = 0; mpz_clear (n); //this simulates log base 2 unsigned int bitsToStoreExponent= 0; unsigned int exponentRange = globals.exponentMax - globals.exponentMin; while (exponentRange >>= 1) ++bitsToStoreExponent; //IMPORTANT ENCODING LOCATED RIGHT HERE IN THIS COMMENT!!! //00 = 6th power, 01=7th, 10=8th, 11=9th, //first 2 bits are for 2, next 2 are for 3, next 2 are for 5, etc. etc. unsigned int exponentCounter = 0; for(Vi::iterator keyExponentValues = it->begin(); ; ) { for (int j=globals.exponentMin; j<globals.exponentMax; j++){ for (int k=0;k<bitsToStoreExponent;k++){ //set i'th prime number bits to appropiate value between 0 and 2^k for exponent value j //globals.exponentMin - j want to turn this into binary representation, get appropriate number for ith place if (k==j){ //keys[counter].primeRepresentation(); //(globals.exponentMin - j) might be useful if (*keyExponentValues % intPow(2,k)==0){//base 10 number convert to base two, get ith digit. keys[counter].primeRepresentation.set(globals.howManyOfFirstNBitsStoredInKey - exponentCounter*bitsToStoreExponent,1); } else{ keys[counter].primeRepresentation.set(globals.howManyOfFirstNBitsStoredInKey - exponentCounter*bitsToStoreExponent,0); } } } } //illustrative but less general example //switch(keyExponentValues->me[i]){ // case 6: // keys[counter].primeRepresentation(); // keys[counter].primeRepresentation.set[32-i*2,0]; // keys[counter].primeRepresentation.set[31-i*2,0]; // break; // case 7: // keys[counter].primeRepresentation(); // keys[counter].primeRepresentation.set[32,0]; // keys[counter].primeRepresentation.set[31,1]; // break; // case 8: // keys[counter].primeRepresentation(); // keys[counter].primeRepresentation.set[32,1]; // keys[counter].primeRepresentation.set[31,0]; // break; // case 9: // keys[counter].primeRepresentation(); // keys[counter].primeRepresentation.set[32,1]; // keys[counter].primeRepresentation.set[31,1]; // break; //} exponentCounter++; keyExponentValues++; } } counter++; it++; } //HERE IS WHERE WE READ THE FILE IN THAT WE WILL ENCODE //TODO move this to a different section //char* input = getInputFromFile(); //unsigned int i = 0; //while (input[i] != '\0'){ //} return 0; }
Paths CorrespondenceGenerator::generate() { Paths result; auto boxA = a->bbox(), boxB = b->bbox(); QStringList nodesA, nodesB; for (auto n : a->nodes) nodesA << n->id; for (auto n : b->nodes) nodesB << n->id; for (auto g : a->groups) for (auto nid : g) nodesA.removeAll(nid); for (auto g : b->groups) for (auto nid : g) nodesB.removeAll(nid); Structure::NodeGroups tmpA, tmpB; for (auto nid : nodesA) tmpA.push_back( QVector<QString>() << nid ); for (auto nid : nodesB) tmpB.push_back( QVector<QString>() << nid ); for (auto g : a->groups) tmpA.push_back(g); for (auto g : b->groups) tmpB.push_back(g); a->groups = tmpA; b->groups = tmpB; /// Build similarity matrix of groups: Eigen::MatrixXd similiarity = Eigen::MatrixXd::Ones(a->groups.size(), b->groups.size() + 1); for (size_t i = 0; i < similiarity.rows(); i++){ double minVal = DBL_MAX; for (size_t j = 0; j < similiarity.cols(); j++){ double val = 0; if (j < b->groups.size()) { Eigen::AlignedBox3d groupBoxA, groupBoxB; for (auto sid : a->groups[i]) groupBoxA.extend(a->getNode(sid)->bbox(1.01)); for (auto sid : b->groups[j]) groupBoxB.extend(b->getNode(sid)->bbox(1.01)); Vector3 relativeCenterA = (groupBoxA.center() - boxA.min()).array() / boxA.sizes().array(); Vector3 relativeCenterB = (groupBoxB.center() - boxB.min()).array() / boxB.sizes().array(); val = (relativeCenterA - relativeCenterB).norm(); minVal = std::min(minVal, val); } similiarity(i, j) = val; } double maxVal = similiarity.row(i).maxCoeff(); if (maxVal == 0) maxVal = 1.0; for (size_t j = 0; j < b->groups.size(); j++) similiarity(i, j) = (similiarity(i, j) - minVal) / maxVal; } std::vector< std::vector<float> > data; for (int i = 0; i < similiarity.rows(); i++){ std::vector<float> dataRow; for (int j = 0; j < similiarity.cols(); j++) dataRow.push_back(similiarity(i, j)); data.push_back(dataRow); } //if (false) showTableColorMap(data, true); // DEBUG // Parameters: double similarity_threshold = 0.4; if (similiarity.rows() < 4) similarity_threshold = 1.0; // Collect good candidates Assignments candidates; for (size_t i = 0; i < similiarity.rows(); i++){ QVector<size_t> candidate; for (size_t j = 0; j < similiarity.cols(); j++){ if (similiarity(i, j) < similarity_threshold) candidate << j; } candidates << candidate; } int count_threshold = 1; Assignments assignments; if (candidates.size() > 7) { debugBox(QString("%1 candidates. Too complex (lower similairty?)").arg(candidates.size())); similarity_threshold = 0.1; Assignments candidates; for (size_t i = 0; i < similiarity.rows(); i++){ QVector<size_t> candidate; for (size_t j = 0; j < similiarity.cols(); j++){ if (similiarity(i, j) < similarity_threshold) candidate << j; } candidates << candidate; } cart_product(assignments, candidates, 10000); count_threshold = 12; } else { cart_product(assignments, candidates); } // Filter assignments Assignments filtered; for (auto & a : assignments) { QMap<size_t, size_t> counts; bool accept = true; auto NOTHING_SEGMENT = similiarity.cols() - 1; for (auto i : a) counts[i]++; for (auto k : counts.keys()) { if (k != NOTHING_SEGMENT && counts[k] > count_threshold){ accept = false; break; } } if (accept) filtered << a; } for (auto & assignment : filtered) { QVector < QStringList > landmarksA, landmarksB; for (size_t i = 0; i < assignment.size(); i++) { if (assignment[i] == b->groups.size()) continue; auto grpA = a->groups[i]; auto grpB = b->groups[assignment[i]]; // Resolve many-to-many if (grpA.size() > 1 && grpB.size() > 1) { QVector<QString> tmpA, tmpB; Eigen::AlignedBox3d groupBoxA, groupBoxB; for (auto sid : grpA) groupBoxA.extend(a->getNode(sid)->bbox(1.01)); for (auto sid : grpB) groupBoxB.extend(b->getNode(sid)->bbox(1.01)); for (auto nodeid_i : grpA){ auto nodeA = a->getNode(nodeid_i); QMap < QString, double > dists; for (auto nodeid_j : grpB){ auto nodeB = b->getNode(nodeid_j); Vector3 posA = (nodeA->position(Eigen::Vector4d(0.5, 0.5, 0, 0)) - boxA.min()).array() / boxA.sizes().array(); Vector3 posB = (nodeB->position(Eigen::Vector4d(0.5, 0.5, 0, 0)) - boxB.min()).array() / boxB.sizes().array(); dists[nodeid_j] = (posA - posB).norm(); } auto nodeid_j = sortQMapByValue(dists).first().second; landmarksA << (QStringList() << nodeid_i); landmarksB << (QStringList() << nodeid_j); } } else { landmarksA << QStringList::fromVector(grpA); landmarksB << QStringList::fromVector(grpB); } } result.push_back( qMakePair(landmarksA, landmarksB) ); } return result; }
void Worker::operator()() { for (private_index=get_index(); private_index!=-1; private_index=get_index()) { {boost::mutex::scoped_lock lock(io_mutex); std::cout << "THREAD " << id << " GOT " << private_index+1 << "/" << Globals::wspd_centers.size() << std::endl;} //Find the side length, radius, radius squared and center of circle/ring for //each one of the circle/rings that I'm going to draw for (int j=0; j<=Globals::wspd_circs_num[private_index]; j++) { //1 as argument because I insert parents of leaves //This means that when I do find a square with this side, I'm going to call //bear_children method again. This essentially reduces processing time by 3/4 sides.push_back(side_discr(pow(2,j)*Globals::wspd_distances[private_index]/denominator,3));//1 // sides.push_back(side_discr(pow(2,j)*Globals::wspd_distances[private_index]/denominator,0)); //make radius an exact multiple of side radiuses.push_back(radius_discr(pow(2,j)*Globals::wspd_distances[private_index], sides[j])); radiuses_sqr.push_back(radiuses[j]*radiuses[j]); //Center of circle should fall neatly on the center of a grid square ANNpoint center = annAllocPt(Globals::dim); for (int k=0; k<Globals::dim; k++) { center[k] = center_discr(Globals::wspd_centers[private_index][k], sides[j], 0.5); } centers.push_back(center); } //first iteration is for the core, the inner circle which is completely filled //the rest of the iteration are rings, essentially 2 concentric cirles where I fill //the difference core=true; for (int circ=0; circ<=Globals::wspd_circs_num[private_index]; circ++) { //Generate all the possible values of a coordinate, based on side and radius //for example if radius is 8 and side is 2 this is going to be 0,2,4,6,8 for (ANNcoord v=0.0; v<=radiuses[circ]; v+=sides[circ]) { all_values.push_back(v); } //cart_prod_counter=0; cart_product(all_values, result, circ); if (Globals::qbs[id]->children!=0) depth_all_reprs(Globals::qbs[id]); // find_all_reprs(Globals::qbs[id], &Globals::hypercube_center, 1.0, kdtree, asdf, id); //CLEANUP all_values.clear(); core=false; } //CLEANUP radiuses.clear(); radiuses_sqr.clear(); sides.clear(); for (unsigned int d=0; d<centers.size(); d++) annDeallocPt(centers[d]); centers.clear(); } std::cout << "THREAD " << id << " DIES" << std::endl; annDeallocPt(qb_center); annDeallocPts(leaf_centers); delete[] leaf_reprs; pos_neg_result.clear(); pos_neg_final.clear(); vd1.clear(); vd2.clear(); delete asdf; delete kdtree; // delete qb; return; }