Static Value-Flow Analysis
Loading...
Searching...
No Matches
Static Public Member Functions | Private Types | Static Private Member Functions | List of all members
SVF::NodeIDAllocator::Clusterer Class Reference

#include <NodeIDAllocator.h>

Static Public Member Functions

static std::vector< NodeIDcluster (BVDataPTAImpl *pta, const std::vector< std::pair< NodeID, unsigned > > keys, std::vector< std::pair< hclust_fast_methods, std::vector< NodeID > > > &candidates, std::string evalSubtitle="")
 
static std::vector< NodeIDgetReverseNodeMapping (const std::vector< NodeID > &nodeMapping)
 
static void evaluate (const std::vector< NodeID > &nodeMap, const Map< PointsTo, unsigned > pointsToSets, Map< std::string, std::string > &stats, bool accountForOcc)
 Fills in *NumWords statistics in stats..
 
static void printStats (std::string title, Map< std::string, std::string > &stats)
 

Private Types

typedef Map< NodePair, std::pair< unsigned, unsigned > > DistOccMap
 

Static Private Member Functions

static size_t condensedIndex (size_t n, size_t i, size_t j)
 
static unsigned requiredBits (const PointsTo &pts)
 Returns the minimum number of bits required to represent pts in a perfect world.
 
static unsigned requiredBits (const size_t n)
 Returns the minimum number of bits required to represent n items in a perfect world.
 
static doublegetDistanceMatrix (const std::vector< std::pair< const PointsTo *, unsigned > > pointsToSets, const size_t numObjects, const Map< NodeID, unsigned > &nodeMap, double &distanceMatrixTime)
 
static void traverseDendrogram (std::vector< NodeID > &nodeMap, const int *dendrogram, const size_t numObjects, unsigned &allocCounter, Set< int > &visited, const int index, const std::vector< NodeID > &regionNodeMap)
 
static std::vector< unsignedregionObjects (const Map< NodeID, Set< NodeID > > &graph, size_t numObjects, size_t &numLabels)
 
static std::pair< hclust_fast_methods, std::vector< NodeID > > determineBestMapping (const std::vector< std::pair< hclust_fast_methods, std::vector< NodeID > > > &candidates, Map< PointsTo, unsigned > pointsToSets, const std::string &evalSubtitle, double &evalTime)
 

Static Private Attributes

static const std::string NumObjects = "NumObjects"
 
static const std::string RegioningTime = "RegioningTime"
 
static const std::string DistanceMatrixTime = "DistanceMatrixTime"
 
static const std::string FastClusterTime = "FastClusterTime"
 
static const std::string DendrogramTraversalTime = "DendrogramTravTime"
 
static const std::string EvalTime = "EvalTime"
 
static const std::string TotalTime = "TotalTime"
 
static const std::string TheoreticalNumWords = "TheoreticalWords"
 
static const std::string OriginalBvNumWords = "OriginalBvWords"
 
static const std::string OriginalSbvNumWords = "OriginalSbvWords"
 
static const std::string NewBvNumWords = "NewBvWords"
 
static const std::string NewSbvNumWords = "NewSbvWords"
 
static const std::string NumRegions = "NumRegions"
 
static const std::string NumGtIntRegions = "NumGtIntRegions"
 
static const std::string LargestRegion = "LargestRegion"
 
static const std::string BestCandidate = "BestCandidate"
 
static const std::string NumNonTrivialRegionObjects = "NumNonTrivObj"
 

Detailed Description

Perform clustering given points-to sets with nodes allocated according to the DENSE strategy.

Definition at line 117 of file NodeIDAllocator.h.

Member Typedef Documentation

◆ DistOccMap

Maps a pair of nodes to their (minimum) distance and the number of times that distance occurs in a set of unique points-to sets.

Definition at line 122 of file NodeIDAllocator.h.

Member Function Documentation

◆ cluster()

std::vector< NodeID > SVF::NodeIDAllocator::Clusterer::cluster ( BVDataPTAImpl pta,
const std::vector< std::pair< NodeID, unsigned > >  keys,
std::vector< std::pair< hclust_fast_methods, std::vector< NodeID > > > &  candidates,
std::string  evalSubtitle = "" 
)
static

Returns vector mapping previously allocated node IDs to a smarter allocation based on the points-to sets in pta accessed through keys. The second part of the keys pairs are the number of (potential) occurrences of that points-to set or a subset, depending on the client's wish. TODO: interfaces are getting unwieldy, an initialised object may be better. TODO: kind of sucks pta can't be const here because getPts isn't.

Definition at line 187 of file NodeIDAllocator.cpp.

188{
189 assert(pta != nullptr && "Clusterer::cluster: given null BVDataPTAImpl");
190 assert(Options::NodeAllocStrat() == Strategy::DENSE && "Clusterer::cluster: only dense allocation clustering currently supported");
191
193 double fastClusterTime = 0.0;
194 double distanceMatrixTime = 0.0;
195 double dendrogramTraversalTime = 0.0;
196 double regioningTime = 0.0;
197 double evalTime = 0.0;
198
199 // Pair of nodes to their (minimum) distance and the number of occurrences of that distance.
200 Map<std::pair<NodeID, NodeID>, std::pair<unsigned, unsigned>> distances;
201
202 double clkStart = PTAStat::getClk(true);
203
204 // Map points-to sets to occurrences.
206
207 // Objects each object shares at least a points-to set with.
209 for (const std::pair<NodeID, unsigned> &keyOcc : keys)
210 {
211 const PointsTo &pts = pta->getPts(keyOcc.first);
212 const size_t oldSize = pointsToSets.size();
213 pointsToSets[pts] += keyOcc.second;;
214
215 // Edges in this graph have no weight or uniqueness, so we only need to
216 // do this for each points-to set once.
217 if (oldSize != pointsToSets.size())
218 {
219 NodeID firstO = !pts.empty() ? *(pts.begin()) : 0;
221 for (const NodeID o : pts)
222 {
223 if (o != firstO)
224 {
225 firstOsNeighbours.insert(o);
226 coPointeeGraph[o].insert(firstO);
227 }
228 }
229 }
230 }
231
233 overallStats[NumObjects] = std::to_string(numObjects);
234
235 size_t numRegions = 0;
236 std::vector<unsigned> objectsRegion;
238 {
240 }
241 else
242 {
243 // Just a single big region (0).
244 objectsRegion.insert(objectsRegion.end(), numObjects, 0);
245 numRegions = 1;
246 }
247
248 // Set needs to be ordered because getDistanceMatrix, in its n^2 iteration, expects
249 // sets to be ordered (we are building a condensed matrix, not a full matrix, so it
250 // matters). In getDistanceMatrix, doing regionReverseMapping for oi and oj, where
251 // oi < oj, and getting a result moi > moj gives incorrect results.
252 // In the condensed matrix, [b][a] where b >= a, is incorrect.
253 std::vector<OrderedSet<NodeID>> regionsObjects(numRegions);
254 for (NodeID o = 0; o < numObjects; ++o) regionsObjects[objectsRegion[o]].insert(o);
255
256 // Size of the return node mapping. It is potentially larger than the number of
257 // objects because we align each region to NATIVE_INT_SIZE.
258 // size_t numMappings = 0;
259
260 // Maps a region to a mapping which maps 0 to n to all objects
261 // in that region.
262 std::vector<std::vector<NodeID>> regionMappings(numRegions);
263 // The reverse: region to mapping of objects to a 0 to n from above.
264 std::vector<Map<NodeID, unsigned>> regionReverseMappings(numRegions);
265 // We can thus use 0 to n for each region to create smaller distance matrices.
266 for (unsigned region = 0; region < numRegions; ++region)
267 {
268 size_t curr = 0;
269 // With the OrderedSet above, o1 < o2 => map[o1] < map[o2].
271 {
272 // push_back here is just like p...[region][curr] = o.
273 regionMappings[region].push_back(o);
275 }
276
277 // curr is the number of objects. A region with no objects makes no sense.
278 assert(curr != 0);
279
280 // Number of bits needed for this region if we were
281 // to start assigning from 0 rounded up to the fewest needed
282 // native ints. This is added to the number of mappings since
283 // we align each region to a native int.
284 // numMappings += requiredBits(regionsObjects[region].size());
285 }
286
287 // Points-to sets which are relevant to a region, i.e., those whose elements
288 // belong to that region. Pair is for occurrences.
289 std::vector<std::vector<std::pair<const PointsTo *, unsigned>>> regionsPointsTos(numRegions);
290 for (const Map<PointsTo, unsigned>::value_type &ptocc : pointsToSets)
291 {
292 const PointsTo &pt = ptocc.first;
293 const unsigned occ = ptocc.second;
294 if (pt.empty()) continue;
295 // Guaranteed that begin() != end() because of the continue above. All objects in pt
296 // will be relevant to the same region.
297 unsigned region = objectsRegion[*(pt.begin())];
298 // In our "graph", objects in the same points-to set have an edge between them,
299 // so they are all in the same connected component/region.
300 regionsPointsTos[region].push_back(std::make_pair(&pt, occ));
301 }
302
303 double clkEnd = PTAStat::getClk(true);
305 overallStats[RegioningTime] = std::to_string(regioningTime);
306 overallStats[NumRegions] = std::to_string(numRegions);
307
308 std::vector<hclust_fast_methods> methods;
310 {
311 methods.push_back(HCLUST_METHOD_SINGLE);
314 }
315 else
316 {
317 methods.push_back(Options::ClusterMethod());
318 }
319
321 {
322 std::vector<NodeID> nodeMap(numObjects, UINT_MAX);
323
324 unsigned numGtIntRegions = 0;
325 unsigned largestRegion = 0;
326 unsigned nonTrivialRegionObjects = 0;
327 unsigned allocCounter = 0;
328 for (unsigned region = 0; region < numRegions; ++region)
329 {
330 const size_t regionNumObjects = regionsObjects[region].size();
331 // Round up to next Word: ceiling of current allocation to get how
332 // many words and multiply to get the number of bits; if we're aligning.
334 {
337 }
338
340
341 // For regions with fewer than 64 objects, we can just allocate them
342 // however as they will be in the one int regardless..
344 {
346 continue;
347 }
348
351
354
356 int *dendrogram = new int[2 * (regionNumObjects - 1)];
357 double *height = new double[regionNumObjects - 1];
359 delete[] distMatrix;
360 delete[] height;
361 clkEnd = PTAStat::getClk(true);
363
365 Set<int> visited;
367 visited, regionNumObjects - 1, regionMappings[region]);
368 delete[] dendrogram;
369 clkEnd = PTAStat::getClk(true);
371 }
372
373 candidates.push_back(std::make_pair(method, nodeMap));
374
375 // Though we "update" these in the loop, they will be the same every iteration.
377 overallStats[LargestRegion] = std::to_string(largestRegion);
379 }
380
381 // Work out which of the mappings we generated looks best.
382 std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = determineBestMapping(candidates, pointsToSets,
384
388 overallStats[EvalTime] = std::to_string(evalTime);
390
392 printStats(evalSubtitle + ": overall", overallStats);
393
394 return bestMapping.second;
395}
#define TIMEINTERVAL
Definition SVFType.h:512
#define NATIVE_INT_SIZE
Size of native integer that we'll use for bit vectors, in bits.
Definition SVFType.h:516
static const std::string DistanceMatrixTime
static const std::string LargestRegion
static const std::string NumNonTrivialRegionObjects
static const std::string EvalTime
static std::vector< unsigned > regionObjects(const Map< NodeID, Set< NodeID > > &graph, size_t numObjects, size_t &numLabels)
static std::pair< hclust_fast_methods, std::vector< NodeID > > determineBestMapping(const std::vector< std::pair< hclust_fast_methods, std::vector< NodeID > > > &candidates, Map< PointsTo, unsigned > pointsToSets, const std::string &evalSubtitle, double &evalTime)
static const std::string BestCandidate
static const std::string DendrogramTraversalTime
static double * getDistanceMatrix(const std::vector< std::pair< const PointsTo *, unsigned > > pointsToSets, const size_t numObjects, const Map< NodeID, unsigned > &nodeMap, double &distanceMatrixTime)
static void traverseDendrogram(std::vector< NodeID > &nodeMap, const int *dendrogram, const size_t numObjects, unsigned &allocCounter, Set< int > &visited, const int index, const std::vector< NodeID > &regionNodeMap)
static void printStats(std::string title, Map< std::string, std::string > &stats)
static const std::string NumRegions
static const std::string RegioningTime
static const std::string NumGtIntRegions
static const std::string FastClusterTime
static const std::string NumObjects
static const std::string TotalTime
static NodeIDAllocator * get(void)
Return (singleton) allocator.
static const OptionMap< SVF::NodeIDAllocator::Strategy > NodeAllocStrat
Definition Options.h:35
static const Option< bool > RegionAlign
Align identifiers in each region to a word.
Definition Options.h:62
static const Option< bool > RegionedClustering
Cluster partitions separately.
Definition Options.h:59
static const OptionMap< enum hclust_fast_methods > ClusterMethod
Definition Options.h:56
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
hclust_fast_methods
Definition fastcluster.h:66
@ HCLUST_METHOD_AVERAGE
Definition fastcluster.h:72
@ HCLUST_METHOD_COMPLETE
Definition fastcluster.h:70
@ HCLUST_METHOD_SVF_BEST
Definition fastcluster.h:76
@ HCLUST_METHOD_SINGLE
Definition fastcluster.h:68
int hclust_fast(int n, double *distmat, int method, int *merge, double *height)
std::string hclustMethodToString(hclust_fast_methods method)
Returns a string representation of a hclust method.
Definition SVFUtil.cpp:261
u32_t NodeID
Definition GeneralType.h:55
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

◆ condensedIndex()

size_t SVF::NodeIDAllocator::Clusterer::condensedIndex ( size_t  n,
size_t  i,
size_t  j 
)
inlinestaticprivate

Returns an index into a condensed matrix (upper triangle, excluding diagonals) corresponding to an nxn matrix.

Definition at line 411 of file NodeIDAllocator.cpp.

412{
413 // From https://stackoverflow.com/a/14839010
414 return n*(n-1)/2 - (n-i)*(n-i-1)/2 + j - i - 1;
415}
cJSON * n
Definition cJSON.cpp:2558

◆ determineBestMapping()

std::pair< hclust_fast_methods, std::vector< NodeID > > SVF::NodeIDAllocator::Clusterer::determineBestMapping ( const std::vector< std::pair< hclust_fast_methods, std::vector< NodeID > > > &  candidates,
Map< PointsTo, unsigned pointsToSets,
const std::string &  evalSubtitle,
double evalTime 
)
inlinestaticprivate

Definition at line 650 of file NodeIDAllocator.cpp.

653{
654 // In case we're not comparing anything, set to first "candidate".
655 std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = candidates[0];
656 // Number of bits required for the best candidate.
657 size_t bestWords = std::numeric_limits<size_t>::max();
659 {
660 for (const std::pair<hclust_fast_methods, std::vector<NodeID>> &candidate : candidates)
661 {
665 std::vector<NodeID> candidateMapping = candidate.second;
666
667 // TODO: parameterise final arg.
668 const double clkStart = PTAStat::getClk(true);
670 const double clkEnd = PTAStat::getClk(true);
673
674 size_t candidateWords = 0;
677 else assert(false && "Clusterer::cluster: unsupported BV type for clustering.");
678
680 {
683 }
684 }
685 }
686
687 return bestMapping;
688}
static const std::string NewSbvNumWords
static void evaluate(const std::vector< NodeID > &nodeMap, const Map< PointsTo, unsigned > pointsToSets, Map< std::string, std::string > &stats, bool accountForOcc)
Fills in *NumWords statistics in stats..
static const std::string NewBvNumWords
static const OptionMap< PointsTo::Type > PtType
Type of points-to set to use for all analyses.
Definition Options.h:50

◆ evaluate()

void SVF::NodeIDAllocator::Clusterer::evaluate ( const std::vector< NodeID > &  nodeMap,
const Map< PointsTo, unsigned pointsToSets,
Map< std::string, std::string > &  stats,
bool  accountForOcc 
)
static

Fills in *NumWords statistics in stats..

Definition at line 572 of file NodeIDAllocator.cpp.

573{
577 u64_t totalNewSbv = 0;
578 u64_t totalNewBv = 0;
579
580 for (const Map<PointsTo, unsigned>::value_type &ptsOcc : pointsToSets)
581 {
582 const PointsTo &pts = ptsOcc.first;
583 const unsigned occ = ptsOcc.second;
584 if (pts.count() == 0) continue;
585
588
589 // Check number of words for original SBV.
590 Set<unsigned> words;
591 // TODO: nasty hardcoding.
592 for (const NodeID o : pts) words.insert(o / 128);
593 u64_t originalSbv = words.size() * 2;
595
596 // Check number of words for original BV.
597 NodeID min = UINT_MAX;
598 NodeID max = 0;
599 for (NodeID o : pts)
600 {
601 if (o < min) min = o;
602 if (o > max) max = o;
603 }
604 words.clear();
605 for (NodeID b = min; b <= max; ++b)
606 {
607 words.insert(b / NATIVE_INT_SIZE);
608 }
609 u64_t originalBv = words.size();
611
612 // Check number of words for new SBV.
613 words.clear();
614 // TODO: nasty hardcoding.
615 for (const NodeID o : pts) words.insert(nodeMap[o] / 128);
616 u64_t newSbv = words.size() * 2;
617 if (accountForOcc) newSbv *= occ;
618
619 // Check number of words for new BV.
620 min = UINT_MAX;
621 max = 0;
622 for (const NodeID o : pts)
623 {
624 const NodeID mappedO = nodeMap[o];
625 if (mappedO < min) min = mappedO;
626 if (mappedO > max) max = mappedO;
627 }
628
629 words.clear();
630 // No nodeMap[b] because min and max and from nodeMap.
631 for (NodeID b = min; b <= max; ++b) words.insert(b / NATIVE_INT_SIZE);
632 u64_t newBv = words.size();
633 if (accountForOcc) newBv *= occ;
634
639 totalNewBv += newBv;
640 }
641
642 stats[TheoreticalNumWords] = std::to_string(totalTheoretical);
643 stats[OriginalSbvNumWords] = std::to_string(totalOriginalSbv);
644 stats[OriginalBvNumWords] = std::to_string(totalOriginalBv);
645 stats[NewSbvNumWords] = std::to_string(totalNewSbv);
646 stats[NewBvNumWords] = std::to_string(totalNewBv);
647}
const cJSON *const b
Definition cJSON.h:255
static const std::string TheoreticalNumWords
static const std::string OriginalSbvNumWords
static unsigned requiredBits(const PointsTo &pts)
Returns the minimum number of bits required to represent pts in a perfect world.
static const std::string OriginalBvNumWords
unsigned long long u64_t
Definition GeneralType.h:48

◆ getDistanceMatrix()

double * SVF::NodeIDAllocator::Clusterer::getDistanceMatrix ( const std::vector< std::pair< const PointsTo *, unsigned > >  pointsToSets,
const size_t  numObjects,
const Map< NodeID, unsigned > &  nodeMap,
double distanceMatrixTime 
)
inlinestaticprivate

Builds the upper triangle of the distance matrix, as an array of length (numObjects * (numObjects - 1)) / 2, as required by fastcluster. Responsibility of caller to delete.

Definition at line 430 of file NodeIDAllocator.cpp.

433{
434 const double clkStart = PTAStat::getClk(true);
435 size_t condensedSize = (numObjects * (numObjects - 1)) / 2;
436 double *distMatrix = new double[condensedSize];
437 for (size_t i = 0; i < condensedSize; ++i) distMatrix[i] = numObjects * numObjects;
438
439 // TODO: maybe use machine epsilon?
440 // For reducing distance due to extra occurrences.
441 // Can differentiate ~9999 occurrences.
442 double occurrenceEpsilon = 0.0001;
443
444 for (const std::pair<const PointsTo *, unsigned> &ptsOcc : pointsToSets)
445 {
446 const PointsTo *pts = ptsOcc.first;
447 assert(pts != nullptr);
448 const unsigned occ = ptsOcc.second;
449
450 // Distance between each element of pts.
452
453 // Use a vector so we can index into pts.
454 std::vector<NodeID> ptsVec;
455 for (const NodeID o : *pts) ptsVec.push_back(o);
456 for (size_t i = 0; i < ptsVec.size(); ++i)
457 {
458 const NodeID oi = ptsVec[i];
459 const Map<NodeID, unsigned>::const_iterator moi = nodeMap.find(oi);
460 assert(moi != nodeMap.end());
461 for (size_t j = i + 1; j < ptsVec.size(); ++j)
462 {
463 const NodeID oj = ptsVec[j];
464 const Map<NodeID, unsigned>::const_iterator moj = nodeMap.find(oj);
465 assert(moj != nodeMap.end());
466 double &existingDistance = distMatrix[condensedIndex(numObjects, moi->second, moj->second)];
467
468 // Subtract extra occurrenceEpsilon to make upcoming logic simpler.
469 // When existingDistance is never whole, it is always between two distances.
471
472 if (distance == std::ceil(existingDistance))
473 {
474 // We have something like distance == x, existingDistance == x - e, for some e < 1
475 // (potentially even set during this iteration).
476 // So, the new distance is an occurrence the existingDistance being tracked, it just
477 // had some reductions because of multiple occurrences.
478 // If there is not room within this distance to reduce more (increase priority),
479 // just ignore it. TODO: maybe warn?
481 {
483 }
484 else
485 {
486 // Reached minimum.
488 }
489 }
490 }
491 }
492
493 }
494
495 const double clkEnd = PTAStat::getClk(true);
497
498 return distMatrix;
499}
static size_t condensedIndex(size_t n, size_t i, size_t j)

◆ getReverseNodeMapping()

std::vector< NodeID > SVF::NodeIDAllocator::Clusterer::getReverseNodeMapping ( const std::vector< NodeID > &  nodeMapping)
static

Definition at line 397 of file NodeIDAllocator.cpp.

398{
399 // nodeMapping.size() may not be big enough because we leave some gaps, but it's a start.
400 std::vector<NodeID> reverseNodeMapping(nodeMapping.size(), UINT_MAX);
401 for (size_t i = 0; i < nodeMapping.size(); ++i)
402 {
403 const NodeID mapsTo = nodeMapping.at(i);
404 if (mapsTo >= reverseNodeMapping.size()) reverseNodeMapping.resize(mapsTo + 1, UINT_MAX);
405 reverseNodeMapping.at(mapsTo) = i;
406 }
407
408 return reverseNodeMapping;
409}

◆ printStats()

void SVF::NodeIDAllocator::Clusterer::printStats ( std::string  title,
Map< std::string, std::string > &  stats 
)
static

Prints statistics to SVFUtil::outs(). TODO: make stats const.

Definition at line 690 of file NodeIDAllocator.cpp.

691{
692 // When not in order, it is too hard to compare original/new SBV/BV words, so this array forces an order.
693 static const std::string statKeys[] =
694 {
700 };
701
702 const unsigned fieldWidth = 20;
703 SVFUtil::outs().flags(std::ios::left);
704 SVFUtil::outs() << "****Clusterer Statistics: " << subtitle << "****\n";
705 for (const std::string& statKey : statKeys)
706 {
707 Map<std::string, std::string>::const_iterator stat = stats.find(statKey);
708 if (stat != stats.end())
709 {
710 SVFUtil::outs() << std::setw(fieldWidth) << statKey << " " << stat->second << "\n";
711 }
712 }
713
714 SVFUtil::outs().flush();
715}
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50

◆ regionObjects()

std::vector< NodeID > SVF::NodeIDAllocator::Clusterer::regionObjects ( const Map< NodeID, Set< NodeID > > &  graph,
size_t  numObjects,
size_t numLabels 
)
inlinestaticprivate

Returns a vector mapping object IDs to a label such that if two objects appear in the same points-to set, they have the same label. The "appear in the same points-to set" is encoded by graph which is an adjacency list ensuring that x in pt(p) and y in pt(p) -> x is reachable from y.

Definition at line 532 of file NodeIDAllocator.cpp.

533{
534 unsigned label = UINT_MAX;
535 std::vector<NodeID> labels(numObjects, UINT_MAX);
537 for (const Map<NodeID, Set<NodeID>>::value_type &oos : graph)
538 {
539 const NodeID o = oos.first;
540 if (labels[o] != UINT_MAX) continue;
541 std::queue<NodeID> bfsQueue;
542 bfsQueue.push(o);
543 ++label;
544 while (!bfsQueue.empty())
545 {
546 const NodeID o = bfsQueue.front();
547 bfsQueue.pop();
548 if (labels[o] != UINT_MAX)
549 {
550 assert(labels[o] == label);
551 continue;
552 }
553
554 labels[o] = label;
555 Map<NodeID, Set<NodeID>>::const_iterator neighboursIt = graph.find(o);
556 assert(neighboursIt != graph.end());
558 }
559 }
560
561 // The remaining objects have no relation with others: they get their own label.
562 for (size_t o = 0; o < numObjects; ++o)
563 {
564 if (labels[o] == UINT_MAX) labels[o] = ++label;
565 }
566
567 numLabels = label + 1;
568
569 return labels;
570}
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map

◆ requiredBits() [1/2]

unsigned SVF::NodeIDAllocator::Clusterer::requiredBits ( const PointsTo pts)
inlinestaticprivate

Returns the minimum number of bits required to represent pts in a perfect world.

Definition at line 417 of file NodeIDAllocator.cpp.

418{
419 return requiredBits(pts.count());
420}

◆ requiredBits() [2/2]

unsigned SVF::NodeIDAllocator::Clusterer::requiredBits ( const size_t  n)
inlinestaticprivate

Returns the minimum number of bits required to represent n items in a perfect world.

Definition at line 422 of file NodeIDAllocator.cpp.

423{
424 if (n == 0) return 0;
425 // Ceiling of number of bits amongst each native integer gives needed native ints,
426 // so we then multiply again by the number of bits in each native int.
427 return ((n - 1) / NATIVE_INT_SIZE + 1) * NATIVE_INT_SIZE;
428}

◆ traverseDendrogram()

void SVF::NodeIDAllocator::Clusterer::traverseDendrogram ( std::vector< NodeID > &  nodeMap,
const int dendrogram,
const size_t  numObjects,
unsigned allocCounter,
Set< int > &  visited,
const int  index,
const std::vector< NodeID > &  regionNodeMap 
)
inlinestaticprivate

Traverses the dendrogram produced by fastcluster, making node o, where o is the nth leaf (per recursive DFS) map to n. index is the dendrogram node to work off. The traversal should start at the top, which is the "last" (consider that it is 2D) element of the dendrogram, numObjects - 1.

Definition at line 501 of file NodeIDAllocator.cpp.

502{
503 if (visited.find(index) != visited.end()) return;
504 visited.insert(index);
505
506 int left = dendrogram[index - 1];
507 if (left < 0)
508 {
509 // Reached a leaf.
510 // -1 because the items start from 1 per fastcluster (TODO).
511 nodeMap[regionNodeMap[std::abs(left) - 1]] = allocCounter;
512 ++allocCounter;
513 }
514 else
515 {
517 }
518
519 // Repeat for the right child.
520 int right = dendrogram[(numObjects - 1) + index - 1];
521 if (right < 0)
522 {
523 nodeMap[regionNodeMap[std::abs(right) - 1]] = allocCounter;
524 ++allocCounter;
525 }
526 else
527 {
529 }
530}
int index
Definition cJSON.h:170

Member Data Documentation

◆ BestCandidate

const std::string SVF::NodeIDAllocator::Clusterer::BestCandidate = "BestCandidate"
staticprivate

Definition at line 141 of file NodeIDAllocator.h.

◆ DendrogramTraversalTime

const std::string SVF::NodeIDAllocator::Clusterer::DendrogramTraversalTime = "DendrogramTravTime"
staticprivate

Definition at line 130 of file NodeIDAllocator.h.

◆ DistanceMatrixTime

const std::string SVF::NodeIDAllocator::Clusterer::DistanceMatrixTime = "DistanceMatrixTime"
staticprivate

Definition at line 128 of file NodeIDAllocator.h.

◆ EvalTime

const std::string SVF::NodeIDAllocator::Clusterer::EvalTime = "EvalTime"
staticprivate

Definition at line 131 of file NodeIDAllocator.h.

◆ FastClusterTime

const std::string SVF::NodeIDAllocator::Clusterer::FastClusterTime = "FastClusterTime"
staticprivate

Definition at line 129 of file NodeIDAllocator.h.

◆ LargestRegion

const std::string SVF::NodeIDAllocator::Clusterer::LargestRegion = "LargestRegion"
staticprivate

Definition at line 140 of file NodeIDAllocator.h.

◆ NewBvNumWords

const std::string SVF::NodeIDAllocator::Clusterer::NewBvNumWords = "NewBvWords"
staticprivate

Definition at line 136 of file NodeIDAllocator.h.

◆ NewSbvNumWords

const std::string SVF::NodeIDAllocator::Clusterer::NewSbvNumWords = "NewSbvWords"
staticprivate

Definition at line 137 of file NodeIDAllocator.h.

◆ NumGtIntRegions

const std::string SVF::NodeIDAllocator::Clusterer::NumGtIntRegions = "NumGtIntRegions"
staticprivate

Definition at line 139 of file NodeIDAllocator.h.

◆ NumNonTrivialRegionObjects

const std::string SVF::NodeIDAllocator::Clusterer::NumNonTrivialRegionObjects = "NumNonTrivObj"
staticprivate

Definition at line 142 of file NodeIDAllocator.h.

◆ NumObjects

const std::string SVF::NodeIDAllocator::Clusterer::NumObjects = "NumObjects"
staticprivate

Statistics strings.

Definition at line 126 of file NodeIDAllocator.h.

◆ NumRegions

const std::string SVF::NodeIDAllocator::Clusterer::NumRegions = "NumRegions"
staticprivate

Definition at line 138 of file NodeIDAllocator.h.

◆ OriginalBvNumWords

const std::string SVF::NodeIDAllocator::Clusterer::OriginalBvNumWords = "OriginalBvWords"
staticprivate

Definition at line 134 of file NodeIDAllocator.h.

◆ OriginalSbvNumWords

const std::string SVF::NodeIDAllocator::Clusterer::OriginalSbvNumWords = "OriginalSbvWords"
staticprivate

Definition at line 135 of file NodeIDAllocator.h.

◆ RegioningTime

const std::string SVF::NodeIDAllocator::Clusterer::RegioningTime = "RegioningTime"
staticprivate

Definition at line 127 of file NodeIDAllocator.h.

◆ TheoreticalNumWords

const std::string SVF::NodeIDAllocator::Clusterer::TheoreticalNumWords = "TheoreticalWords"
staticprivate

Definition at line 133 of file NodeIDAllocator.h.

◆ TotalTime

const std::string SVF::NodeIDAllocator::Clusterer::TotalTime = "TotalTime"
staticprivate

Definition at line 132 of file NodeIDAllocator.h.


The documentation for this class was generated from the following files: