int main() { PdmSuperClusterer super; PdmCWDClusterer clust(&super, POL_LEFTCIRCULAR); // guestimates for TSS; match test data super.setObsParams(2289 - 5.034399, 64, 0.6958917); while(cin) { int count, bin, drift, power; cin >> count; cin >> bin; cin >> drift; cin >> power; clust.recordHit(bin,drift,power); } clust.allHitsLoaded(); super.compute(); printf("found %d superclusters:\n", super.getCount()); for (int i = 0; i < super.getCount(); i++) { const PdmClusterTag &tag = super.getNthMainSignal(i); dumpTag("SUPER ",tag); for (int j = 0; j < super.getNthClusterCount(i); j++) { const PdmClusterTag &tag2 = super.getNthMthCluster(i,j); dumpTag(" ",tag2); } } return 0; }
void FExtrudeMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float a, s; Point3 pt, center; int c; pblock->GetValue(PB_AMOUNT,t,a,iv); pblock->GetValue(PB_SCALE,t,s,iv); pblock->GetValue(PB_CENTER,t,c,iv); base->GetValue(t,&pt,iv,CTRL_ABSOLUTE); // Extrude the faces -- this just creates the new faces mesh.ExtrudeFaces(); // Build normals of selected faces only Tab<Point3> normals; if (!c) { normals.SetCount(mesh.getNumVerts()); for (int i=0; i<mesh.getNumVerts(); i++) { normals[i] = Point3(0,0,0); } for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) { Point3 norm = (mesh.verts[mesh.faces[i].v[1]]-mesh.verts[mesh.faces[i].v[0]]) ^ (mesh.verts[mesh.faces[i].v[2]]-mesh.verts[mesh.faces[i].v[1]]); for (int j=0; j<3; j++) { normals[mesh.faces[i].v[j]] += norm; } } } for (int i=0; i<mesh.getNumVerts(); i++) { normals[i] = Normalize(normals[i]); } } else { // Compute the center point base->GetValue(t,¢er,iv,CTRL_ABSOLUTE); } // Mark vertices used by selected faces BitArray sel; sel.SetSize(mesh.getNumVerts()); for (int i=0; i<mesh.getNumFaces(); i++) { if (mesh.faceSel[i]) { for (int j=0; j<3; j++) sel.Set(mesh.faces[i].v[j],TRUE); } } // Move selected verts for (int i=0; i<mesh.getNumVerts(); i++) { if (sel[i]) { if (!c) { mesh.verts[i] += normals[i]*a; } else { Point3 vect = Normalize((mesh.verts[i] * (*mc.tm)) - center); mesh.verts[i] += vect*a; } } } // Scale verts if (s!=100.0f) { s /= 100.0f; AdjEdgeList ae(mesh); AdjFaceList af(mesh,ae); FaceClusterList clust(mesh.faceSel,af); // Make sure each vertex is only scaled once. BitArray done; done.SetSize(mesh.getNumVerts()); // scale each cluster independently for (int i=0; (DWORD)i<clust.count; i++) { // First determine cluster center Point3 cent(0,0,0); int ct=0; for (int j=0; j<mesh.getNumFaces(); j++) { if (clust[j]==(DWORD)i) { for (int k=0; k<3; k++) { cent += mesh.verts[mesh.faces[j].v[k]]; ct++; } } } if (ct) cent /= float(ct); // Now scale the cluster about its center for (int j=0; j<mesh.getNumFaces(); j++) { if (clust[j]==(DWORD)i) { for (int k=0; k<3; k++) { int index = mesh.faces[j].v[k]; if (done[index]) continue; done.Set(index); mesh.verts[index] = (mesh.verts[index]-cent)*s + cent; } } } } } mesh.InvalidateTopologyCache (); os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); } }
void testCWDCluster() { PdmSuperClusterer super; PdmCWDClusterer clust(&super, POL_LEFTCIRCULAR); // with nothing added, should return empty vector clust.allHitsLoaded(); super.compute(); int count = super.getCount(); ASSERT_EQ(0, count); // with one hit added, should return 1 supercluster describing that hit super.clear(); clust.recordHit(100,5,50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // after clear, should return empty vector super.clear(); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(0, count); // with two hits added far apart, // should return 2 superclusters describing each hit super.clear(); clust.recordHit(100,5,50); clust.recordHit(2100,5,50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(2, count); // verify description PdmClusterTag tag; tag = super.getNthMainSignal(0); CwPowerSignal cw = tag.holder->getCWD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), cw.sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5)/clust.getSecondsPerObs(), cw.sig.drift, D_FREQ); ASSERT_EQ_F(50, cw.sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), cw.sig.width, D_FREQ); tag = super.getNthMainSignal(1); cw = tag.holder->getCWD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(2100), cw.sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5)/clust.getSecondsPerObs(), cw.sig.drift, D_FREQ); ASSERT_EQ_F(50, cw.sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), cw.sig.width, D_FREQ); // with two equally powered hits added within the lev1 range // should return 1 supercluster describing first hit, with // width set to number of bins from lowest to highest hit, inclusive super.clear(); clust.recordHit(100,5,50); clust.recordHit(102,5,50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); cw = tag.holder->getCWD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), cw.sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5)/clust.getSecondsPerObs(), cw.sig.drift, D_FREQ); ASSERT_EQ_F(50, cw.sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(3), cw.sig.width, D_FREQ); // with three unequally powered hits added within the lev1 range // should return 1 supercluster describing highest power hit, with // width set to number of bins from lowest to highest hit, inclusive super.clear(); clust.recordHit(100,5,50); clust.recordHit(102,5,52); clust.recordHit(104,5,51); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); cw = tag.holder->getCWD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(102), cw.sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5)/clust.getSecondsPerObs(), cw.sig.drift, D_FREQ); ASSERT_EQ_F(52, cw.sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5), cw.sig.width, D_FREQ); // with two equally powered hits added outside the lev1 range but // within the lev2 range // should return 1 supercluster describing first hit super.clear(); clust.recordHit(100,5,50); clust.recordHit(200,5,50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); cw = tag.holder->getCWD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), cw.sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5)/clust.getSecondsPerObs(), cw.sig.drift, D_FREQ); ASSERT_EQ_F(50, cw.sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), cw.sig.width, D_FREQ); // with unequally powered hits added outside the lev1 range but // within the lev2 range // should return 1 supercluster describing highest power hit super.clear(); clust.recordHit(100,5,50); clust.recordHit(200,5,52); clust.recordHit(300,5,51); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); cw = tag.holder->getCWD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(200), cw.sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(5)/clust.getSecondsPerObs(), cw.sig.drift, D_FREQ); ASSERT_EQ_F(52, cw.sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), cw.sig.width, D_FREQ); super.clear(); }
void testPDCluster() { PdmSuperClusterer super; PdmPDClusterer clust(&super, RES_1HZ); // with nothing added, should return empty vector clust.allHitsLoaded(); super.compute(); int count = super.getCount(); ASSERT_EQ(0, count); // with one hit added, should return 1 supercluster describing that hit // "bogus" triplets should get stripped super.clear(); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 50, 4, 102, 50, 6, 103, 50); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 0, 4, 102, 50, 6, 103, 50); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 50, 4, 102, 0, 6, 103, 50); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 50, 4, 102, 50, 6, 103, 0); clust.recordTriplet(POL_LEFTCIRCULAR, 4, 101, 50, 4, 102, 50, 4, 103, 50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // after clear, should return empty vector super.clear(); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(0, count); // with two hits added far apart, // should return 2 superclusters describing each hit super.clear(); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 50, 4, 102, 50, 6, 103, 50); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 2101, 50, 4, 2102, 50, 6, 2103, 50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(2, count); // verify description PdmClusterTag tag; tag = super.getNthMainSignal(0); const PulseSignalHeader *pd = &tag.holder->getPD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), pd->sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(32)/clust.getSecondsPerObs(), pd->sig.drift, D_FREQ); ASSERT_EQ_F(3*50, pd->sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), pd->sig.width, D_FREQ); tag = super.getNthMainSignal(1); pd = &tag.holder->getPD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(2100), pd->sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(32)/clust.getSecondsPerObs(), pd->sig.drift, D_FREQ); ASSERT_EQ_F(3*50, pd->sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), pd->sig.width, D_FREQ); // with three triplets in the lev1 range, should calculate a path // through all pulses with unique spectra. Only the strongest // pulse for a given spectrum number is retained. Power should // sum over all included pulses super.clear(); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 8, 4, 102, 2, 6, 103, 4); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 111, 1, 4, 102, 16, 6, 113, 32); clust.recordTriplet(POL_LEFTCIRCULAR, 6, 103, 64, 8, 104, 128, 10, 105, 256); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); pd = &tag.holder->getPD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), pd->sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(32)/clust.getSecondsPerObs(), pd->sig.drift, D_FREQ); ASSERT_EQ_F(8+16+64+128+256, pd->sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1+10*((float)2/3)), pd->sig.width, D_FREQ); // check pulse period ASSERT_EQ_F(2.0 * clust.getSecondsPerObs() / clust.getSpectraPerObs(), pd->train.pulsePeriod, D_PERIOD); // check individual pulses ASSERT_EQ(5, pd->train.numberOfPulses); Pulse *p = (Pulse *)(pd+1); ASSERT_EQ_F(clust.binsToAbsoluteMHz(101), p[0].frequency, D_FREQ); ASSERT_EQ(8, (int)p[0].power); ASSERT_EQ(2, p[0].spectrumNumber); ASSERT_EQ_F(clust.binsToAbsoluteMHz(102), p[1].frequency, D_FREQ); ASSERT_EQ(16, (int)p[1].power); ASSERT_EQ(4, p[1].spectrumNumber); ASSERT_EQ_F(clust.binsToAbsoluteMHz(103), p[2].frequency, D_FREQ); ASSERT_EQ(64, (int)p[2].power); ASSERT_EQ(6, p[2].spectrumNumber); ASSERT_EQ_F(clust.binsToAbsoluteMHz(104), p[3].frequency, D_FREQ); ASSERT_EQ(128, (int)p[3].power); ASSERT_EQ(8, p[3].spectrumNumber); ASSERT_EQ_F(clust.binsToAbsoluteMHz(105), p[4].frequency, D_FREQ); ASSERT_EQ(256, (int)p[4].power); ASSERT_EQ(10, p[4].spectrumNumber); // with two equally powered hits added outside the lev1 range but // within the lev2 range // should return 1 supercluster describing first hit super.clear(); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 50, 4, 102, 50, 6, 103, 50); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 201, 50, 4, 202, 50, 6, 203, 50); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); pd = &tag.holder->getPD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), pd->sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(32)/clust.getSecondsPerObs(), pd->sig.drift, D_FREQ); ASSERT_EQ_F(3*50, pd->sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), pd->sig.width, D_FREQ); // with unequally powered hits added outside the lev1 range but // within the lev2 range // should return 1 supercluster describing highest power hit super.clear(); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 101, 50, 4, 102, 50, 6, 103, 50); clust.recordTriplet(POL_LEFTCIRCULAR, 2, 201, 60, 4, 202, 60, 6, 203, 60); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); pd = &tag.holder->getPD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(200), pd->sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(32)/clust.getSecondsPerObs(), pd->sig.drift, D_FREQ); ASSERT_EQ_F(3*60, pd->sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), pd->sig.width, D_FREQ); // check pulse period ASSERT_EQ_F(2.0 * clust.getSecondsPerObs() / clust.getSpectraPerObs(), pd->train.pulsePeriod, D_PERIOD); // check individual pulses ASSERT_EQ(3, pd->train.numberOfPulses); p = (Pulse *)(pd+1); ASSERT_EQ_F(clust.binsToAbsoluteMHz(201), p[0].frequency, D_FREQ); ASSERT_EQ(60, (int)p[0].power); ASSERT_EQ(2, p[0].spectrumNumber); ASSERT_EQ_F(clust.binsToAbsoluteMHz(202), p[1].frequency, D_FREQ); ASSERT_EQ(60, (int)p[1].power); ASSERT_EQ(4, p[1].spectrumNumber); ASSERT_EQ_F(clust.binsToAbsoluteMHz(203), p[2].frequency, D_FREQ); ASSERT_EQ(60, (int)p[2].power); ASSERT_EQ(6, p[2].spectrumNumber); // pulse period test -- 3 triplets; two with one period and one with // another; should take most common period super.clear(); clust.recordTriplet(POL_LEFTCIRCULAR, 8, 104, 10, 10, 105, 10, 12, 106, 10); clust.recordTriplet(POL_LEFTCIRCULAR, 14, 107, 10, 18, 109, 10, 22, 111, 10); clust.recordTriplet(POL_LEFTCIRCULAR, 26, 113, 10, 30, 115, 10, 34, 117, 10); clust.allHitsLoaded(); super.compute(); count = super.getCount(); ASSERT_EQ(1, count); // verify description tag = super.getNthMainSignal(0); pd = &tag.holder->getPD()->getNth(tag.index); ASSERT_EQ_F(clust.binsToAbsoluteMHz(100), pd->sig.rfFreq, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(32)/clust.getSecondsPerObs(), pd->sig.drift, D_FREQ); ASSERT_EQ_F(9*10, pd->sig.power, D_FREQ); ASSERT_EQ_F(clust.binsToRelativeHz(1), pd->sig.width, D_FREQ); // check pulse period ASSERT_EQ_F(4.0 * clust.getSecondsPerObs() / clust.getSpectraPerObs(), pd->train.pulsePeriod, D_PERIOD); super.clear(); }
int main() { std::shared_ptr<util::DissimMatrix> l1ptr = parseFile("/home/srmq/Dropbox/CIn/research/inria/dados/iris-L1-1-N.csv"); std::shared_ptr<util::DissimMatrix> l2ptr = parseFile("/home/srmq/Dropbox/CIn/research/inria/dados/iris-L1-2-N.csv"); std::shared_ptr<util::DissimMatrix> l3ptr = parseFile("/home/srmq/Dropbox/CIn/research/inria/dados/iris-L1-3-N.csv"); std::shared_ptr<util::DissimMatrix> l4ptr = parseFile("/home/srmq/Dropbox/CIn/research/inria/dados/iris-L1-4-N.csv"); std::vector<std::shared_ptr<util::DissimMatrix>> dissimMatrices = {l1ptr, l2ptr, l3ptr, l4ptr}; const int NUMBER_OF_RUNS = 100; int k = 3; bool possibilisticMode = false; double bestJ = std::numeric_limits<double>::max(); std::shared_ptr<std::vector<util::FuzzyCluster> > bestClusters; const int classLabelLength = 150; int classlabels[classLabelLength]; for (int i = 0; i < classLabelLength; i++) { classlabels[i] = i/50; } const unsigned int procCount = std::thread::hardware_concurrency(); if (procCount > 1) { unsigned int procId = 0; bool quitwhile = false; int pipeParentChild[procCount][2]; // PARENT WRITES to CHILD, CHILD READS from PARENT int pipeChildParent[procCount][2]; // PARENT READS from CHILD, CHILD WRITES to PARENT pid_t cpid; do { if (pipe(pipeParentChild[procId]) == -1) { perror("pipe"); exit(EXIT_FAILURE); } if (pipe(pipeChildParent[procId]) == -1) { perror("pipe"); exit(EXIT_FAILURE); } cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* I am the child */ // close WRITE in pipeParentChild close(pipeParentChild[procId][1]); // close READ in pipeChildParent close(pipeChildParent[procId][0]); quitwhile = true; } else { /* I am the master */ // close READ in pipeParentChild close(pipeParentChild[procId][0]); // close WRITE in pipeChildParent close(pipeChildParent[procId][1]); procId++; } } while (procId < procCount && !quitwhile); if (cpid == 0) { /* I am the child do stuff */ clustering::FWRDCA::seed_random_engine(2u*procId + 1u); for (int i = procId; i < NUMBER_OF_RUNS; i=i+procCount) { std::cout << "Run number "; std::cout << i; std::cout << std::endl; clustering::FWRDCA clust(dissimMatrices); clust.setPossibilisticMode(possibilisticMode); clust.cluster(k); std::shared_ptr<std::vector<util::FuzzyCluster> > const myClusters = clust.getClusters(); const double myJ = clust.calcJ(myClusters); std::cout << "J: "; std::cout << myJ; std::cout << std::endl; if (myJ < bestJ) { bestJ = myJ; bestClusters = clust.getClustersCopy(); } } write(pipeChildParent[procId][1], &bestJ, sizeof(double)); close(pipeChildParent[procId][1]); bool amITheBest; read(pipeParentChild[procId][0], &amITheBest, sizeof(bool)); // le resultado if (amITheBest) { printIndices(k, classLabelLength, bestClusters, classlabels); } } else { /* I am the master get results */ double overallBestJ; read(pipeChildParent[0][0], &overallBestJ, sizeof(double)); // le resultado unsigned int bestIndex = 0; for (unsigned int i = 1; i < procCount; i++) { double procBestJ; read(pipeChildParent[i][0], &procBestJ, sizeof(double)); // le resultado if (procBestJ > overallBestJ) { overallBestJ = procBestJ; bestIndex = i; } } const bool falseConst = false; const bool trueConst = true; for (unsigned int i = 0; i < procCount; i++) { if (i != bestIndex) { write(pipeParentChild[i][1], &falseConst, sizeof(bool)); close(pipeParentChild[i][1]); } else { write(pipeParentChild[i][1], &trueConst, sizeof(bool)); close(pipeParentChild[i][1]); } } } } else { for (int i = 0; i < NUMBER_OF_RUNS; i++) { std::cout << "Run number "; std::cout << i; std::cout << std::endl; clustering::FWRDCA clust(dissimMatrices); clust.setPossibilisticMode(possibilisticMode); clust.cluster(k); std::shared_ptr<std::vector<util::FuzzyCluster> > const myClusters = clust.getClusters(); const double myJ = clust.calcJ(myClusters); std::cout << "J: "; std::cout << myJ; std::cout << std::endl; if (myJ < bestJ) { bestJ = myJ; bestClusters = clust.getClustersCopy(); } } printIndices(k, classLabelLength, bestClusters, classlabels); } return(0); }
SEXP kmeansMatrixEuclid(MatrixType x, index_type n, index_type m, SEXP pcen, SEXP pclust, SEXP pclustsizes, SEXP pwss, SEXP itermax) { index_type j, col, nchange; int maxiters = Rf_asInteger(itermax); SEXP Riter; Rf_protect(Riter = Rf_allocVector(INTSXP, 1)); int *iter = INTEGER(Riter); iter[0] = 0; BigMatrix *pcent = reinterpret_cast<BigMatrix*>(R_ExternalPtrAddr(pcen)); MatrixAccessor<double> cent(*pcent); BigMatrix *Pclust = reinterpret_cast<BigMatrix*>(R_ExternalPtrAddr(pclust)); MatrixAccessor<int> clust(*Pclust); BigMatrix *Pclustsizes = reinterpret_cast<BigMatrix*>(R_ExternalPtrAddr(pclustsizes)); MatrixAccessor<double> clustsizes(*Pclustsizes); BigMatrix *Pwss = reinterpret_cast<BigMatrix*>(R_ExternalPtrAddr(pwss)); MatrixAccessor<double> ss(*Pwss); int k = (int) pcent->nrow(); // number of clusters int cl, bestcl, oldcluster, newcluster; int done = 0; double temp; vector<double> d(k); // Vector of distances, internal only. vector<double> temp1(k); vector<vector<double> > tempcent(m, temp1); // For copy of global centroids k x m // At this point I can use [][] to access things, with ss[0][cl] // being used for the vectors, for example. // Before starting the loop, we only have cent (centers) as passed into the function. // Calculate clust and clustsizes, then update cent as centroids. for (cl=0; cl<k; cl++) clustsizes[0][cl] = 0.0; for (j=0; j<n; j++) { bestcl = 0; for (cl=0; cl<k; cl++) { d[cl] = 0.0; for (col=0; col<m; col++) { temp = (double)x[col][j] - cent[col][cl]; d[cl] += temp * temp; } if (d[cl]<d[bestcl]) bestcl = cl; } clust[0][j] = bestcl + 1; // Saving the R cluster number, not the C index. clustsizes[0][bestcl]++; for (col=0; col<m; col++) tempcent[col][bestcl] += (double)x[col][j]; } for (cl=0; cl<k; cl++) for (col=0; col<m; col++) cent[col][cl] = tempcent[col][cl] / clustsizes[0][cl]; do { nchange = 0; for (j=0; j<n; j++) { // For each of my points, this is offset from hash position oldcluster = clust[0][j] - 1; bestcl = 0; for (cl=0; cl<k; cl++) { // Consider each of the clusters d[cl] = 0.0; // We'll get the distance to this cluster. for (col=0; col<m; col++) { // Loop over the dimension of the data temp = (double)x[col][j] - cent[col][cl]; d[cl] += temp * temp; } if (d[cl]<d[bestcl]) bestcl = cl; } // End of looking over the clusters for this j if (d[bestcl] < d[oldcluster]) { // MADE A CHANGE! newcluster = bestcl; clust[0][j] = newcluster + 1; nchange++; clustsizes[0][newcluster]++; clustsizes[0][oldcluster]--; for (col=0; col<m; col++) { cent[col][oldcluster] += ( cent[col][oldcluster] - (double)x[col][j] ) / clustsizes[0][oldcluster]; cent[col][newcluster] += ( (double)x[col][j] - cent[col][newcluster] ) / clustsizes[0][newcluster]; } } } // End of this pass over my points. iter[0]++; if ( (nchange==0) || (iter[0]>=maxiters) ) done = 1; } while (done==0); // Collect the sums of squares now that we're done. for (cl=0; cl<k; cl++) ss[0][cl] = 0.0; for (j=0; j<n; j++) { for (col=0; col<m; col++) { cl = clust[0][j]-1; temp = (double)x[col][j] - cent[col][cl]; ss[0][cl] += temp * temp; } } Rf_unprotect(1); return(Riter); }