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="", bool printStat=true)
 
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, bool printStat)
 

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 131 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 136 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 = "",
bool  printStat = true 
)
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 193 of file NodeIDAllocator.cpp.

200{
201 assert(pta != nullptr && "Clusterer::cluster: given null BVDataPTAImpl");
202 assert(Options::NodeAllocStrat() == Strategy::DENSE && "Clusterer::cluster: only dense allocation clustering currently supported");
203
205 double fastClusterTime = 0.0;
206 double distanceMatrixTime = 0.0;
207 double dendrogramTraversalTime = 0.0;
208 double regioningTime = 0.0;
209 double evalTime = 0.0;
210
211 // Pair of nodes to their (minimum) distance and the number of occurrences of that distance.
212 Map<std::pair<NodeID, NodeID>, std::pair<unsigned, unsigned>> distances;
213
214 double clkStart = PTAStat::getClk(true);
215
216 // Map points-to sets to occurrences.
218
219 // Objects each object shares at least a points-to set with.
221 for (const std::pair<NodeID, unsigned> &keyOcc : keys)
222 {
223 const PointsTo &pts = pta->getPts(keyOcc.first);
224 const size_t oldSize = pointsToSets.size();
225 pointsToSets[pts] += keyOcc.second;;
226
227 // Edges in this graph have no weight or uniqueness, so we only need to
228 // do this for each points-to set once.
229 if (oldSize != pointsToSets.size())
230 {
231 NodeID firstO = !pts.empty() ? *(pts.begin()) : 0;
233 for (const NodeID o : pts)
234 {
235 if (o != firstO)
236 {
237 firstOsNeighbours.insert(o);
238 coPointeeGraph[o].insert(firstO);
239 }
240 }
241 }
242 }
243
245 overallStats[NumObjects] = std::to_string(numObjects);
246
247 size_t numRegions = 0;
248 std::vector<unsigned> objectsRegion;
250 {
252 }
253 else
254 {
255 // Just a single big region (0).
256 objectsRegion.insert(objectsRegion.end(), numObjects, 0);
257 numRegions = 1;
258 }
259
260 // Set needs to be ordered because getDistanceMatrix, in its n^2 iteration, expects
261 // sets to be ordered (we are building a condensed matrix, not a full matrix, so it
262 // matters). In getDistanceMatrix, doing regionReverseMapping for oi and oj, where
263 // oi < oj, and getting a result moi > moj gives incorrect results.
264 // In the condensed matrix, [b][a] where b >= a, is incorrect.
265 std::vector<OrderedSet<NodeID>> regionsObjects(numRegions);
266 for (NodeID o = 0; o < numObjects; ++o) regionsObjects[objectsRegion[o]].insert(o);
267
268 // Size of the return node mapping. It is potentially larger than the number of
269 // objects because we align each region to NATIVE_INT_SIZE.
270 // size_t numMappings = 0;
271
272 // Maps a region to a mapping which maps 0 to n to all objects
273 // in that region.
274 std::vector<std::vector<NodeID>> regionMappings(numRegions);
275 // The reverse: region to mapping of objects to a 0 to n from above.
276 std::vector<Map<NodeID, unsigned>> regionReverseMappings(numRegions);
277 // We can thus use 0 to n for each region to create smaller distance matrices.
278 for (unsigned region = 0; region < numRegions; ++region)
279 {
280 size_t curr = 0;
281 // With the OrderedSet above, o1 < o2 => map[o1] < map[o2].
283 {
284 // push_back here is just like p...[region][curr] = o.
285 regionMappings[region].push_back(o);
287 }
288
289 // curr is the number of objects. A region with no objects makes no sense.
290 assert(curr != 0);
291
292 // Number of bits needed for this region if we were
293 // to start assigning from 0 rounded up to the fewest needed
294 // native ints. This is added to the number of mappings since
295 // we align each region to a native int.
296 // numMappings += requiredBits(regionsObjects[region].size());
297 }
298
299 // Points-to sets which are relevant to a region, i.e., those whose elements
300 // belong to that region. Pair is for occurrences.
301 std::vector<std::vector<std::pair<const PointsTo *, unsigned>>> regionsPointsTos(numRegions);
302 for (const Map<PointsTo, unsigned>::value_type &ptocc : pointsToSets)
303 {
304 const PointsTo &pt = ptocc.first;
305 const unsigned occ = ptocc.second;
306 if (pt.empty()) continue;
307 // Guaranteed that begin() != end() because of the continue above. All objects in pt
308 // will be relevant to the same region.
309 unsigned region = objectsRegion[*(pt.begin())];
310 // In our "graph", objects in the same points-to set have an edge between them,
311 // so they are all in the same connected component/region.
312 regionsPointsTos[region].push_back(std::make_pair(&pt, occ));
313 }
314
315 double clkEnd = PTAStat::getClk(true);
317 overallStats[RegioningTime] = std::to_string(regioningTime);
318 overallStats[NumRegions] = std::to_string(numRegions);
319
320 std::vector<hclust_fast_methods> methods;
322 {
323 methods.push_back(HCLUST_METHOD_SINGLE);
326 }
327 else
328 {
330 }
331
333 {
334 std::vector<NodeID> nodeMap(numObjects, UINT_MAX);
335
336 unsigned numGtIntRegions = 0;
337 unsigned largestRegion = 0;
338 unsigned nonTrivialRegionObjects = 0;
339 unsigned allocCounter = 0;
340 for (unsigned region = 0; region < numRegions; ++region)
341 {
342 const size_t regionNumObjects = regionsObjects[region].size();
343 // Round up to next Word: ceiling of current allocation to get how
344 // many words and multiply to get the number of bits; if we're aligning.
346 {
349 }
350
352
353 // For regions with fewer than 64 objects, we can just allocate them
354 // however as they will be in the one int regardless..
356 {
358 continue;
359 }
360
363
366
368 int *dendrogram = new int[2 * (regionNumObjects - 1)];
369 double *height = new double[regionNumObjects - 1];
371 delete[] distMatrix;
372 delete[] height;
373 clkEnd = PTAStat::getClk(true);
375
377 Set<int> visited;
379 visited, regionNumObjects - 1, regionMappings[region]);
380 delete[] dendrogram;
381 clkEnd = PTAStat::getClk(true);
383 }
384
385 candidates.push_back(std::make_pair(method, nodeMap));
386
387 // Though we "update" these in the loop, they will be the same every iteration.
389 overallStats[LargestRegion] = std::to_string(largestRegion);
391 }
392
393 // Work out which of the mappings we generated looks best.
394 std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping =
395 determineBestMapping(candidates, pointsToSets, evalSubtitle, evalTime, printStat);
396
400 overallStats[EvalTime] = std::to_string(evalTime);
402
404 if (printStat)
405 {
406 printStats(evalSubtitle + ": overall", overallStats);
407 }
408
409 return bestMapping.second;
410}
#define TIMEINTERVAL
Definition SVFType.h:621
#define NATIVE_INT_SIZE
Size of native integer that we'll use for bit vectors, in bits.
Definition SVFType.h:625
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 const std::string BestCandidate
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, bool printStat)
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:32
static const Option< bool > RegionAlign
Align identifiers in each region to a word.
Definition Options.h:59
static const Option< bool > RegionedClustering
Cluster partitions separately.
Definition Options.h:56
static const OptionMap< u32_t > ClusterMethod
Definition Options.h:53
static double getClk(bool mark=false)
Definition SVFStat.cpp:51
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:252
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ 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 426 of file NodeIDAllocator.cpp.

427{
428 // From https://stackoverflow.com/a/14839010
429 return n*(n-1)/2 - (n-i)*(n-i-1)/2 + j - i - 1;
430}
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,
bool  printStat 
)
inlinestaticprivate

Definition at line 665 of file NodeIDAllocator.cpp.

672{
673 // In case we're not comparing anything, set to first "candidate".
674 std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = candidates[0];
675 // Number of bits required for the best candidate.
676 size_t bestWords = std::numeric_limits<size_t>::max();
678 {
679 for (const std::pair<hclust_fast_methods, std::vector<NodeID>> &candidate : candidates)
680 {
684 std::vector<NodeID> candidateMapping = candidate.second;
685
686 // TODO: parameterise final arg.
687 const double clkStart = PTAStat::getClk(true);
689 const double clkEnd = PTAStat::getClk(true);
691 if (printStat)
692 {
694 }
695
696 size_t candidateWords = 0;
699 else assert(false && "Clusterer::cluster: unsupported BV type for clustering.");
700
702 {
705 }
706 }
707 }
708
709 return bestMapping;
710}
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:47

◆ 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 587 of file NodeIDAllocator.cpp.

588{
592 u64_t totalNewSbv = 0;
593 u64_t totalNewBv = 0;
594
595 for (const Map<PointsTo, unsigned>::value_type &ptsOcc : pointsToSets)
596 {
597 const PointsTo &pts = ptsOcc.first;
598 const unsigned occ = ptsOcc.second;
599 if (pts.count() == 0) continue;
600
603
604 // Check number of words for original SBV.
605 Set<unsigned> words;
606 // TODO: nasty hardcoding.
607 for (const NodeID o : pts) words.insert(o / 128);
608 u64_t originalSbv = words.size() * 2;
610
611 // Check number of words for original BV.
612 NodeID min = UINT_MAX;
613 NodeID max = 0;
614 for (NodeID o : pts)
615 {
616 if (o < min) min = o;
617 if (o > max) max = o;
618 }
619 words.clear();
620 for (NodeID b = min; b <= max; ++b)
621 {
622 words.insert(b / NATIVE_INT_SIZE);
623 }
624 u64_t originalBv = words.size();
626
627 // Check number of words for new SBV.
628 words.clear();
629 // TODO: nasty hardcoding.
630 for (const NodeID o : pts) words.insert(nodeMap[o] / 128);
631 u64_t newSbv = words.size() * 2;
632 if (accountForOcc) newSbv *= occ;
633
634 // Check number of words for new BV.
635 min = UINT_MAX;
636 max = 0;
637 for (const NodeID o : pts)
638 {
639 const NodeID mappedO = nodeMap[o];
640 if (mappedO < min) min = mappedO;
641 if (mappedO > max) max = mappedO;
642 }
643
644 words.clear();
645 // No nodeMap[b] because min and max and from nodeMap.
646 for (NodeID b = min; b <= max; ++b) words.insert(b / NATIVE_INT_SIZE);
647 u64_t newBv = words.size();
648 if (accountForOcc) newBv *= occ;
649
654 totalNewBv += newBv;
655 }
656
657 stats[TheoreticalNumWords] = std::to_string(totalTheoretical);
658 stats[OriginalSbvNumWords] = std::to_string(totalOriginalSbv);
659 stats[OriginalBvNumWords] = std::to_string(totalOriginalBv);
660 stats[NewSbvNumWords] = std::to_string(totalNewSbv);
661 stats[NewBvNumWords] = std::to_string(totalNewBv);
662}
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:49

◆ 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 445 of file NodeIDAllocator.cpp.

448{
449 const double clkStart = PTAStat::getClk(true);
450 size_t condensedSize = (numObjects * (numObjects - 1)) / 2;
451 double *distMatrix = new double[condensedSize];
452 for (size_t i = 0; i < condensedSize; ++i) distMatrix[i] = numObjects * numObjects;
453
454 // TODO: maybe use machine epsilon?
455 // For reducing distance due to extra occurrences.
456 // Can differentiate ~9999 occurrences.
457 double occurrenceEpsilon = 0.0001;
458
459 for (const std::pair<const PointsTo *, unsigned> &ptsOcc : pointsToSets)
460 {
461 const PointsTo *pts = ptsOcc.first;
462 assert(pts != nullptr);
463 const unsigned occ = ptsOcc.second;
464
465 // Distance between each element of pts.
467
468 // Use a vector so we can index into pts.
469 std::vector<NodeID> ptsVec;
470 for (const NodeID o : *pts) ptsVec.push_back(o);
471 for (size_t i = 0; i < ptsVec.size(); ++i)
472 {
473 const NodeID oi = ptsVec[i];
474 const Map<NodeID, unsigned>::const_iterator moi = nodeMap.find(oi);
475 assert(moi != nodeMap.end());
476 for (size_t j = i + 1; j < ptsVec.size(); ++j)
477 {
478 const NodeID oj = ptsVec[j];
479 const Map<NodeID, unsigned>::const_iterator moj = nodeMap.find(oj);
480 assert(moj != nodeMap.end());
481 double &existingDistance = distMatrix[condensedIndex(numObjects, moi->second, moj->second)];
482
483 // Subtract extra occurrenceEpsilon to make upcoming logic simpler.
484 // When existingDistance is never whole, it is always between two distances.
486
487 if (distance == std::ceil(existingDistance))
488 {
489 // We have something like distance == x, existingDistance == x - e, for some e < 1
490 // (potentially even set during this iteration).
491 // So, the new distance is an occurrence the existingDistance being tracked, it just
492 // had some reductions because of multiple occurrences.
493 // If there is not room within this distance to reduce more (increase priority),
494 // just ignore it. TODO: maybe warn?
496 {
498 }
499 else
500 {
501 // Reached minimum.
503 }
504 }
505 }
506 }
507
508 }
509
510 const double clkEnd = PTAStat::getClk(true);
512
513 return distMatrix;
514}
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 412 of file NodeIDAllocator.cpp.

413{
414 // nodeMapping.size() may not be big enough because we leave some gaps, but it's a start.
415 std::vector<NodeID> reverseNodeMapping(nodeMapping.size(), UINT_MAX);
416 for (size_t i = 0; i < nodeMapping.size(); ++i)
417 {
418 const NodeID mapsTo = nodeMapping.at(i);
419 if (mapsTo >= reverseNodeMapping.size()) reverseNodeMapping.resize(mapsTo + 1, UINT_MAX);
420 reverseNodeMapping.at(mapsTo) = i;
421 }
422
423 return reverseNodeMapping;
424}

◆ 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 712 of file NodeIDAllocator.cpp.

713{
714 // When not in order, it is too hard to compare original/new SBV/BV words, so this array forces an order.
715 static const std::string statKeys[] =
716 {
722 };
723
724 const unsigned fieldWidth = 20;
725 SVFUtil::outs().flags(std::ios::left);
726 SVFUtil::outs() << "****Clusterer Statistics: " << subtitle << "****\n";
727 for (const std::string& statKey : statKeys)
728 {
729 Map<std::string, std::string>::const_iterator stat = stats.find(statKey);
730 if (stat != stats.end())
731 {
732 SVFUtil::outs() << std::setw(fieldWidth) << statKey << " " << stat->second << "\n";
733 }
734 }
735
736 SVFUtil::outs().flush();
737}
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52

◆ 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 547 of file NodeIDAllocator.cpp.

548{
549 unsigned label = UINT_MAX;
550 std::vector<NodeID> labels(numObjects, UINT_MAX);
552 for (const Map<NodeID, Set<NodeID>>::value_type &oos : graph)
553 {
554 const NodeID o = oos.first;
555 if (labels[o] != UINT_MAX) continue;
556 std::queue<NodeID> bfsQueue;
557 bfsQueue.push(o);
558 ++label;
559 while (!bfsQueue.empty())
560 {
561 const NodeID o = bfsQueue.front();
562 bfsQueue.pop();
563 if (labels[o] != UINT_MAX)
564 {
565 assert(labels[o] == label);
566 continue;
567 }
568
569 labels[o] = label;
570 Map<NodeID, Set<NodeID>>::const_iterator neighboursIt = graph.find(o);
571 assert(neighboursIt != graph.end());
573 }
574 }
575
576 // The remaining objects have no relation with others: they get their own label.
577 for (size_t o = 0; o < numObjects; ++o)
578 {
579 if (labels[o] == UINT_MAX) labels[o] = ++label;
580 }
581
582 numLabels = label + 1;
583
584 return labels;
585}
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 432 of file NodeIDAllocator.cpp.

433{
434 return requiredBits(pts.count());
435}

◆ 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 437 of file NodeIDAllocator.cpp.

438{
439 if (n == 0) return 0;
440 // Ceiling of number of bits amongst each native integer gives needed native ints,
441 // so we then multiply again by the number of bits in each native int.
442 return ((n - 1) / NATIVE_INT_SIZE + 1) * NATIVE_INT_SIZE;
443}

◆ 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 516 of file NodeIDAllocator.cpp.

517{
518 if (visited.find(index) != visited.end()) return;
519 visited.insert(index);
520
521 int left = dendrogram[index - 1];
522 if (left < 0)
523 {
524 // Reached a leaf.
525 // -1 because the items start from 1 per fastcluster (TODO).
526 nodeMap[regionNodeMap[std::abs(left) - 1]] = allocCounter;
527 ++allocCounter;
528 }
529 else
530 {
532 }
533
534 // Repeat for the right child.
535 int right = dendrogram[(numObjects - 1) + index - 1];
536 if (right < 0)
537 {
538 nodeMap[regionNodeMap[std::abs(right) - 1]] = allocCounter;
539 ++allocCounter;
540 }
541 else
542 {
544 }
545}
int index
Definition cJSON.h:170

Member Data Documentation

◆ BestCandidate

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

Definition at line 155 of file NodeIDAllocator.h.

◆ DendrogramTraversalTime

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

Definition at line 144 of file NodeIDAllocator.h.

◆ DistanceMatrixTime

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

Definition at line 142 of file NodeIDAllocator.h.

◆ EvalTime

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

Definition at line 145 of file NodeIDAllocator.h.

◆ FastClusterTime

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

Definition at line 143 of file NodeIDAllocator.h.

◆ LargestRegion

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

Definition at line 154 of file NodeIDAllocator.h.

◆ NewBvNumWords

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

Definition at line 150 of file NodeIDAllocator.h.

◆ NewSbvNumWords

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

Definition at line 151 of file NodeIDAllocator.h.

◆ NumGtIntRegions

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

Definition at line 153 of file NodeIDAllocator.h.

◆ NumNonTrivialRegionObjects

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

Definition at line 156 of file NodeIDAllocator.h.

◆ NumObjects

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

Statistics strings.

Definition at line 140 of file NodeIDAllocator.h.

◆ NumRegions

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

Definition at line 152 of file NodeIDAllocator.h.

◆ OriginalBvNumWords

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

Definition at line 148 of file NodeIDAllocator.h.

◆ OriginalSbvNumWords

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

Definition at line 149 of file NodeIDAllocator.h.

◆ RegioningTime

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

Definition at line 141 of file NodeIDAllocator.h.

◆ TheoreticalNumWords

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

Definition at line 147 of file NodeIDAllocator.h.

◆ TotalTime

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

Definition at line 146 of file NodeIDAllocator.h.


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