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

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

425{
426 // From https://stackoverflow.com/a/14839010
427 return n*(n-1)/2 - (n-i)*(n-i-1)/2 + j - i - 1;
428}
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 663 of file NodeIDAllocator.cpp.

670{
671 // In case we're not comparing anything, set to first "candidate".
672 std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = candidates[0];
673 // Number of bits required for the best candidate.
674 size_t bestWords = std::numeric_limits<size_t>::max();
676 {
677 for (const std::pair<hclust_fast_methods, std::vector<NodeID>> &candidate : candidates)
678 {
682 std::vector<NodeID> candidateMapping = candidate.second;
683
684 // TODO: parameterise final arg.
685 const double clkStart = PTAStat::getClk(true);
687 const double clkEnd = PTAStat::getClk(true);
689 if (printStat)
690 {
692 }
693
694 size_t candidateWords = 0;
697 else assert(false && "Clusterer::cluster: unsupported BV type for clustering.");
698
700 {
703 }
704 }
705 }
706
707 return bestMapping;
708}
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:46

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

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

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

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

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

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

711{
712 // When not in order, it is too hard to compare original/new SBV/BV words, so this array forces an order.
713 static const std::string statKeys[] =
714 {
720 };
721
722 const unsigned fieldWidth = 20;
723 SVFUtil::outs().flags(std::ios::left);
724 SVFUtil::outs() << "****Clusterer Statistics: " << subtitle << "****\n";
725 for (const std::string& statKey : statKeys)
726 {
727 Map<std::string, std::string>::const_iterator stat = stats.find(statKey);
728 if (stat != stats.end())
729 {
730 SVFUtil::outs() << std::setw(fieldWidth) << statKey << " " << stat->second << "\n";
731 }
732 }
733
734 SVFUtil::outs().flush();
735}
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 545 of file NodeIDAllocator.cpp.

546{
547 unsigned label = UINT_MAX;
548 std::vector<NodeID> labels(numObjects, UINT_MAX);
550 for (const Map<NodeID, Set<NodeID>>::value_type &oos : graph)
551 {
552 const NodeID o = oos.first;
553 if (labels[o] != UINT_MAX) continue;
554 std::queue<NodeID> bfsQueue;
555 bfsQueue.push(o);
556 ++label;
557 while (!bfsQueue.empty())
558 {
559 const NodeID o = bfsQueue.front();
560 bfsQueue.pop();
561 if (labels[o] != UINT_MAX)
562 {
563 assert(labels[o] == label);
564 continue;
565 }
566
567 labels[o] = label;
568 Map<NodeID, Set<NodeID>>::const_iterator neighboursIt = graph.find(o);
569 assert(neighboursIt != graph.end());
571 }
572 }
573
574 // The remaining objects have no relation with others: they get their own label.
575 for (size_t o = 0; o < numObjects; ++o)
576 {
577 if (labels[o] == UINT_MAX) labels[o] = ++label;
578 }
579
580 numLabels = label + 1;
581
582 return labels;
583}
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition GeneralType.h:56

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

431{
432 return requiredBits(pts.count());
433}

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

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

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

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