Skip to content

Commit

Permalink
Merge ca34425 into 986dc9a
Browse files Browse the repository at this point in the history
  • Loading branch information
manpen committed Jul 1, 2019
2 parents 986dc9a + ca34425 commit 6f99105
Show file tree
Hide file tree
Showing 24 changed files with 3,176 additions and 4 deletions.
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,12 @@ endif()
################################################################################
# Use TLX as a CMake submodule
if(EXISTS "${PROJECT_SOURCE_DIR}/extlibs/tlx/CMakeLists.txt")
add_subdirectory(extlibs/tlx)
if(EXISTS "${PROJECT_SOURCE_DIR}/extlibs/tlx/tlx/math/power_to_the.hpp")
add_subdirectory(extlibs/tlx)
else()
message(FATAL_ERROR "It seems the TLX submodule is out-of-date"
"Please run `git submodule update` to update the submodule.")
endif()
else()
message(FATAL_ERROR
"Missing TLX library in extlibs/tlx "
Expand Down
2 changes: 1 addition & 1 deletion extlibs/tlx
Submodule tlx updated 46 files
+3 −0 CMakeLists.txt
+2 −2 README.md
+1 −0 tests/CMakeLists.txt
+36 −28 tests/container/btree_speedtest.cpp
+53 −46 tests/container/btree_speedtest.plot
+ tests/container/btree_speedtest_results.pdf
+3 −0 tests/container/loser_tree_test.cpp
+143 −0 tests/container/splay_tree_test.cpp
+7 −0 tests/die_test.cpp
+54 −3 tests/math_test.cpp
+76 −16 tests/string_test.cpp
+2 −0 tlx/CMakeLists.txt
+11 −0 tlx/cmdline_parser.cpp
+3 −0 tlx/cmdline_parser.hpp
+1 −0 tlx/container.hpp
+18 −15 tlx/container/btree.hpp
+348 −0 tlx/container/splay_tree.hpp
+34 −0 tlx/die.hpp
+3 −0 tlx/die/core.cpp
+67 −0 tlx/die/core.hpp
+30 −7 tlx/logger/core.cpp
+5 −1 tlx/logger/core.hpp
+1 −1 tlx/main.dox
+2 −0 tlx/math.hpp
+1 −1 tlx/math/div_ceil.hpp
+44 −0 tlx/math/power_to_the.hpp
+35 −0 tlx/math/round_up.hpp
+14 −4 tlx/semaphore.hpp
+9 −1 tlx/string.hpp
+85 −0 tlx/string/bitdump.cpp
+92 −0 tlx/string/bitdump.hpp
+82 −21 tlx/string/ends_with.cpp
+28 −4 tlx/string/ends_with.hpp
+31 −0 tlx/string/format_iec_units.hpp
+2 −18 tlx/string/format_si_iec_units.hpp
+31 −0 tlx/string/format_si_units.hpp
+83 −0 tlx/string/hash_djb2.hpp
+82 −0 tlx/string/hash_sdbm.hpp
+3 −3 tlx/string/join_generic.hpp
+62 −0 tlx/string/ssprintf.cpp
+46 −0 tlx/string/ssprintf.hpp
+94 −0 tlx/string/ssprintf_generic.hpp
+49 −16 tlx/string/starts_with.cpp
+27 −3 tlx/string/starts_with.hpp
+1 −1 tlx/thread_pool.hpp
+1 −1 tlx/version.hpp
Empty file added include/networkit/ext/NOLINT
Empty file.
92 changes: 92 additions & 0 deletions include/networkit/generators/GeometricInhomogenousGenerator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* GeometricInhomogenousGenerator.h
*
* Created on: 09.05.2019
* Author: Manuel Penschuck <networkit@manuel.jetzt>
*/

#ifndef GEOMETRICINHOMOGENOUS_H_
#define GEOMETRICINHOMOGENOUS_H_

#include <limits>
#include <vector>

#include <networkit/generators/StaticGraphGenerator.hpp>

namespace NetworKit {

class GeometricInhomogenousGenerator: public StaticGraphGenerator {
public:
using Coordinate = std::vector<double>;

/**
* @param[in] n Number of nodes
* @param[in] avgDegree The desired average degree with 0 < avgDegree < n-1
* @param[in] powerlawExp Target exponent of power-law distribution with powerlawExp > 2.0
* @param[in] alpha parameter (1/temperature) with alpha > 1
* @param[in] dimension Dimension of the underlying geometry with 1 <= dimension <= 5
*/
GeometricInhomogenousGenerator(count n, double avgDegree, double powerlawExp=3, double alpha=std::numeric_limits<double>::infinity(), unsigned dim=1);

/**
* Construct generator from weights that are then scale to match avgDegree and T.
*
* @param[in] points Coordinates of points
* @param[in] weights Unscaled weights (assumed to be powerlaw distributed)
* @param[in] avgDegree The desired average degree with 0 < avgDegree < n-1
* @param[in] alpha parameter (1/temperature) with alpha > 1
*
* @warning points and weights are moved into the container. The we're not using
* rvalue refs because Cython does not handle them.
*/
GeometricInhomogenousGenerator(std::vector<Coordinate> points, std::vector<double> weights, double avgDegree, double alpha);

/**
* Construct generator from *already scaled* weights.
*
* @param[in] points Coordinates of points
* @param[in] weights *Scaled* weights
* @param[in] alpha parameter (1/temperature) with alpha > 1
*
* @warning points and weights are moved into the container. The we're not using
* rvalue refs because Cython does not handle them.
*/
GeometricInhomogenousGenerator(std::vector<Coordinate> points, std::vector<double> weights, double alpha);

// Add virtual destructor
virtual ~GeometricInhomogenousGenerator() = default;

/// @return Graph to be generated according to parameters specified in constructor freeing memory by deleting the input point set.
Graph generate() override;

/// @return Graph to be generated according to parameters specified in constructor keeping the input point set.
Graph generateKeepingInput();

/**
* @return Weights used to generate the graph
* @warning The data is destroyed if generate is called with keep_input = false (default).
*/
const std::vector<double>& weights() const noexcept {
return pointWeights;
}

/**
* @return Point positions used to generate the graph
* @warning The data is destroyed if generate is called with keep_input = false (default).
*/
const std::vector<Coordinate>& positions() const noexcept {
return pointPositions;
}

private:
double alpha;

std::vector<Coordinate> pointPositions;
std::vector<double> pointWeights;

void checkInputParameters() const;
};

} // NetworKit

#endif // GEOMETRICINHOMOGENOUS_H_
133 changes: 132 additions & 1 deletion networkit/_NetworKit.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2140,8 +2140,139 @@ cdef class ErdosRenyiGenerator(StaticGraphGenerator):
p = (2 * m) / (scale * n * (n-1))
return cls(scale * n, p)

cdef extern from "<networkit/generators/DorogovtsevMendesGenerator.hpp>":

cdef extern from "<networkit/generators/GeometricInhomogenousGenerator.hpp>":
cdef cppclass _GeometricInhomogenousGenerator "NetworKit::GeometricInhomogenousGenerator"(_StaticGraphGenerator):
_GeometricInhomogenousGenerator(count n, double avgDegree, double powerlawExp, double alpha, unsigned dim) except +
_GeometricInhomogenousGenerator(vector[vector[double]] points, vector[double] weights, double alpha) except +
_GeometricInhomogenousGenerator(vector[vector[double]] points, vector[double] weights, double avgDegree, double alpha) except +
_Graph generateKeepingInput() except +
const vector[double]& weights()
const vector[vector[double]]& positions()

cdef class GeometricInhomogenousGenerator(StaticGraphGenerator):
"""
Creates a Geometric Inhomogenous Random Graph by first samling n random points in a d-dimension space
and then connecting them according to their weights and distances. It implements the generator of
Blaesius et al. "Efficiently Generating Geometric Inhomogeneous and Hyperbolic Random Graphs" [https://arxiv.org/abs/1905.06706]
GeometricInhomogenousGenerator(count numNodes, double avgDegree, double powerlawExp, double alpha, unsigned dimensions)
Creates G(nNodes, prob) graphs.
see also: GeometricInhomogenousGenerator.fromPoints() to create a graph from an explicitly provided point set.
Parameters
----------
numNodes : count
Number of nodes n in the graph.
avgDegree : double
Desired average degree -- will be met only in expection, though variance is quite small.
powerlawExp : double
Exponenent of the powerlaw degree distribution with powerlawExp > 2
alpha : double
Alpha parameter (1 / Temperature) with alpha > 1
dimensions : unsigned
Number of dimensions in the underlying geometric with 1 <= dimensions <= 5
"""

# these values are used to delay construction of self._this; do not rely on these values,
# as they are not properly set if constructed via fromPoints!
cdef int _numNodes
cdef double _avgDegree
cdef double _powerlawExp
cdef double _alpha
cdef int _dimensions

def __cinit__(self, numNodes, avgDegree, powerlawExp = 3, alpha = math.inf, dimensions = 1):
# params is only used in _constructOnDemand; it is not well-defined if constructed with fromPoints(..)
self._numNodes = numNodes
self._avgDegree = avgDegree
self._powerlawExp = powerlawExp
self._alpha = alpha
self._dimensions = dimensions

@staticmethod # cannot used @classmethod as we need to bind the cls's type in order for the cdefs to work
def fromPoints(positions, weights, alpha = math.inf, avgDegree = None):
"""
Creates a Geometric Inhomogenous Random Graph from a point set provided.
GeometricInhomogenousFromPointSetGenerator(self, vector[vector[double]] positions, vector[double] weights, double alpha = math.inf, avgDegree = None)
Parameters
----------
positions : vector[ vector[double] ]
A vector of one position for each node. A position is a vector with d entries between 0.0 and 1.0.
All points have to have the same dimension d with 1 <= d <= 5.
weights : vector[double]
Weights for each point
alpha : double
Alpha parameter (1 / Temperature) with alpha > 1
avgDegree : double
Desired average degree, if omitted (= None) the weights provided are used directly without scaling
"""
assert(len(positions) == len(weights))

self = GeometricInhomogenousGenerator(len(positions), 0)

if avgDegree is None:
self._this = new _GeometricInhomogenousGenerator(positions, weights, alpha)
else:
self._this = new _GeometricInhomogenousGenerator(positions, weights, avgDegree, alpha)

return self

def getWeights(self):
"""
Returns a list of node weights.
This data is automatically deleted during the execution of generate. If you want to access it,
either do so BEFORE calling generate or use generateKeepingInput instead
"""
self._constructOnDemand()
return (<_GeometricInhomogenousGenerator*>(self._this)).weights()

def getPositions(self):
"""
Returns a list of node positions.
This data is automatically deleted during the execution of generate. If you want to access it,
either do so BEFORE calling generate or use generateKeepingInput instead
"""
self._constructOnDemand()
return (<_GeometricInhomogenousGenerator*>(self._this)).positions()

def generate(self):
"""
Generates the graph.
Returns
-------
networkit.Graph
"""
self._constructOnDemand()
return Graph().setThis((<_GeometricInhomogenousGenerator*>(self._this)).generate())

def generateKeepingInput(self):
"""
Same generate() but keep the input point set.
"""
self._constructOnDemand()
return Graph().setThis((<_GeometricInhomogenousGenerator*>(self._this)).generateKeepingInput())

cdef _constructOnDemand(self):
"""
INTERNAL METHOD, DO NOT CALL DIRECTLY
Constructs the C++ instance wrapper (if not done so yet)
"""
if self._this != NULL:
return

self._this = new _GeometricInhomogenousGenerator(self._numNodes, self._avgDegree,
self._powerlawExp, self._alpha, self._dimensions)


cdef extern from "<networkit/generators/DorogovtsevMendesGenerator.hpp>":
cdef cppclass _DorogovtsevMendesGenerator "NetworKit::DorogovtsevMendesGenerator"(_StaticGraphGenerator):
_DorogovtsevMendesGenerator(count nNodes) except +

Expand Down
5 changes: 5 additions & 0 deletions networkit/cpp/generators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ networkit_add_module(generators
DynamicPubWebGenerator.cpp
EdgeSwitchingMarkovChainGenerator.cpp
ErdosRenyiGenerator.cpp
GeometricInhomogenousGenerator.cpp
girgs/Generator.cpp
girgs/WeightScaling.cpp
HavelHakimiGenerator.cpp
HyperbolicGenerator.cpp
LFRGenerator.cpp
Expand All @@ -29,8 +32,10 @@ networkit_add_module(generators
WattsStrogatzGenerator.cpp
)


networkit_module_link_modules(generators
auxiliary base dynamics geometric graph structures)

add_subdirectory(girgs)
add_subdirectory(quadtree)
add_subdirectory(test)
92 changes: 92 additions & 0 deletions networkit/cpp/generators/GeometricInhomogenousGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* GeometricInhomogenousGenerator.cpp
*
* Created on: 09.05.2019
* Author: Manuel Penschuck <networkit@manuel.jetzt>
*/

#include <networkit/generators/GeometricInhomogenousGenerator.hpp>
#include "girgs/Generator.hpp"

namespace NetworKit {


GeometricInhomogenousGenerator::GeometricInhomogenousGenerator(count n, double avgDegree, double exp, double alpha, unsigned dim) :
alpha(alpha)
// do not initialize pointWeights and pointPosition here to check paremeters before
{
if (alpha <= 1)
throw std::runtime_error("Temperature T has to satiesfy 0 <= T < 1");

if (!(1 <= dim && dim <= 5))
throw std::runtime_error("Support only 1 to 5 dimensions");

if (n >= static_cast<count>(std::numeric_limits<int>::max()))
throw std::runtime_error("Support only INT_MAX nodes");

pointPositions = girgs::generatePositions(static_cast<int>(n), dim, true);
pointWeights = girgs::generateWeights(static_cast<int>(n), exp, true);
girgs::scaleWeights(pointWeights, avgDegree, dim, alpha);
}

GeometricInhomogenousGenerator::GeometricInhomogenousGenerator(std::vector<Coordinate> points, std::vector<double> weights, double avgDegree, double alpha) :
alpha(alpha),
pointPositions(std::move(points)),
pointWeights(std::move(weights))
{
checkInputParameters();
const auto dim = static_cast<int>(pointPositions.front().size());
girgs::scaleWeights(pointWeights, avgDegree, dim, alpha);
}

// Construct without scaling
GeometricInhomogenousGenerator::GeometricInhomogenousGenerator(std::vector<Coordinate> points, std::vector<double> weights, double alpha) :
alpha(alpha),
pointPositions(std::move(points)),
pointWeights(std::move(weights))
{
checkInputParameters();
}

Graph GeometricInhomogenousGenerator::generate() {
return girgs::generateEdges(pointWeights, pointPositions, alpha, false);
}

Graph GeometricInhomogenousGenerator::generateKeepingInput() {
return girgs::generateEdges(pointWeights, pointPositions, alpha, true);
}

void GeometricInhomogenousGenerator::checkInputParameters() const {
if (alpha <= 1)
throw std::runtime_error("Alpha has to be larger than 1");


if (!pointPositions.size())
throw std::runtime_error("Generator requires at least one point");


if (pointPositions.size() != pointWeights.size())
throw std::runtime_error("Number of nodes in vectors points and weight do not match");


const auto dim = pointPositions.front().size();
if (!(1 <= dim && dim <= 5))
throw std::runtime_error("Support only 1 to 5 dimensions");


#ifndef NDEBUG
for(const auto& pt : pointPositions) {
if (pt.size() != dim)
throw std::runtime_error("All points have to have the same dimension");


for(const auto x : pt) {
if (!(0 <= x && x <= 1))
throw std::runtime_error("Points have to lie within the [0:1]^d unit hypercube");

}
}
#endif
}

} // NetworKit

0 comments on commit 6f99105

Please sign in to comment.