40namespace energybased {
74 template<
typename ForceFunc,
bool UseForcePrime>
78 template<
typename ForceFunc,
bool UseForcePrime>
82 template<
typename ForceFunc,
bool UseForcePrime>
86 template<
typename AttrForceFunc,
bool UseForcePrime>
91 void computeEdgeForcesSq();
100 template<
typename RepForceFunc>
101 double doIteration(RepForceFunc repForceFunc);
104 double doIteration() {
return doIteration(RepForceFunctionInvDist<Dim>); };
107 template<
typename RepForceFunc>
108 void doIterations(
int numIterations,
double epsilon, RepForceFunc repForceFunc);
111 template<
typename RepForceFunc>
112 void doIterations(
int numIterations,
double epsilon);
116 template<
typename RepForceFunc,
typename AttrForceFunc,
bool UseForcePrime>
117 void doIterationsTempl(
int numIterations,
double epsilon, RepForceFunc repForceFunc,
118 AttrForceFunc attrForceFunc);
120 template<
typename RepForceFunc,
typename AttrForceFunc>
122 AttrForceFunc attrForceFunc);
124 template<
typename RepForceFunc,
typename AttrForceFunc>
126 AttrForceFunc attrForceFunc);
129 template<
typename RepForceFunc>
130 void doIterationsAdaptive(
int numIterations,
double epsilon, RepForceFunc repForceFunc);
197template<
typename ForceFunc,
bool UseForcePrime>
202 for (
node s = m_graph.firstNode(); s; s = s->succ()) {
204 double dist = computeDeltaAndDistance<Dim>(m_nodeInfo[s].position,
205 m_nodeInfo[t].position, delta);
208 forceFunc(dist, force, force_prime);
210 force = force / dist * mass(s) * mass(t);
213 for (
int d = 0; d < Dim; d++) {
214 m_nodeInfo[s].force[d] += force * delta[d];
215 m_nodeInfo[t].force[d] -= force * delta[d];
219 force_prime = force_prime * mass(s) * mass(t);
220 m_nodeInfo[s].force_prime += force_prime;
221 m_nodeInfo[t].force_prime += force_prime;
229template<
typename ForceFunc>
234 for (
node s = m_graph.firstNode(); s; s = s->succ()) {
236 double dist = computeDeltaAndDistance<Dim>(m_nodeInfo[s].position, m_nodeInfo[t].position, delta);
239 forceFunc(dist, force);
241 force = force / dist * mass(s) * mass(t);
244 for (
int d = 0; d < Dim; d++) {
245 m_nodeInfo[s].force[d] += force * delta[d];
246 m_nodeInfo[s].force[d] += force * delta[d];
254template<
typename ForceFunc,
bool UseForcePrime>
258 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
260 for (
int d = 0; d < Dim; d++) {
261 m_pTreeForce->setPosition(currIndex, d, m_nodeInfo[v].position[d]);
265 m_pTreeForce->setMass(currIndex, m_nodeInfo[v].mass);
270 m_pTreeForce->template computeForces<ForceFunc, UseForcePrime>(forceFunc);
276 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
278 for (
int d = 0; d < Dim; d++) {
279 m_nodeInfo[v].force[d] += m_pTreeForce->force(currIndex, d);
283 m_nodeInfo[v].force_prime += m_pTreeForce->force_prime(currIndex);
292template<
typename ForceFunc>
297 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
299 for (
int d = 0; d < Dim; d++) {
300 m_pTreeForce->
setPosition(currIndex, d, m_nodeInfo[v].position[d]);
304 m_pTreeForce->setMass(currIndex, m_nodeInfo[v].mass);
309 m_pTreeForce->template computeForces<ForceFunc, true>(forceFunc);
315 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
317 for (
int d = 0; d < Dim; d++) {
318 m_nodeInfo[v].force[d] += m_pTreeForce->force(currIndex, d);
327template<
typename ForceFunc,
bool UseForcePrime>
329 if (m_graph.numberOfNodes() <= m_maxNumNodesExactRepForces) {
330 computeRepForcesExact<ForceFunc, UseForcePrime>(forceFunc);
332 computeRepForcesApprox<ForceFunc, UseForcePrime>(forceFunc);
338template<
typename ForceFunc>
341 if (m_graph.numberOfNodes() <= m_maxNumNodesExactRepForces) {
342 computeRepForcesExactNewton(forceFunc);
344 computeRepForcesApproxNewton(forceFunc);
350template<
typename AttrForceFunc,
bool UseForcePrime>
353 for (
edge e = m_graph.firstEdge(); e; e = e->succ()) {
354 node s = e->source();
355 node t = e->target();
366 double dist_sq = 0.0;
369 for (
int d = 0; d < Dim; d++) {
370 delta[d] = m_nodeInfo[t].position[d] - m_nodeInfo[s].position[d];
371 dist_sq += delta[d] * delta[d];
376 double f =
log(dist_sq) * 0.5;
378 double dist = (sqrt(dist_sq));
384 attrForceFunc(dist, f, f_prime);
386 f_prime *= m_edgeWeight[e];
388 m_nodeInfo[s].force_prime += f_prime;
389 m_nodeInfo[t].force_prime += f_prime;
391 attrForceFunc(dist, f, f_prime);
394 f *= m_edgeWeight[e];
397 for (
int d = 0; d < Dim; d++) {
398 m_nodeInfo[s].force[d] += f * delta[d] / dist;
399 m_nodeInfo[t].force[d] -= f * delta[d] / dist;
406template<
typename AttrForceFunc>
410 for (
edge e = m_graph.firstEdge(); e; e = e->succ()) {
411 node s = e->source();
412 node t = e->target();
423 double dist_sq = 0.0;
426 for (
int d = 0; d < Dim; d++) {
427 delta[d] = m_nodeInfo[t].position[d] - m_nodeInfo[s].position[d];
428 dist_sq += delta[d] * delta[d];
433 double f =
log(dist_sq) * 0.5;
435 double dist = (sqrt(dist_sq));
436 double f = (dist) * (dist) * m_edgeWeight[e];
437 double f_prime = 2.0 * dist * m_edgeWeight[e];
440 double s_scale = 1.0/(double)s->
degree();
441 double t_scale = 1.0/(double)t->
degree();
444 m_nodeInfo[s].force_prime += f_prime;
445 m_nodeInfo[t].force_prime += f_prime;
448 for (
int d = 0; d < Dim; d++) {
449 m_nodeInfo[s].force[d] += f * delta[d] / dist;
450 m_nodeInfo[t].force[d] -= f * delta[d] / dist;
456void DTreeEmbedder<Dim>::computeEdgeForcesSq()
458 for (
node s = m_graph.firstNode(); s; s = s->
succ()) {
462 double sum_ddf = 0.0;
464 for (
int d = 0; d < Dim; d++) {
470 node t = adj->twinNode();
480 double dist_sq = 0.0;
483 for (
int d = 0; d < Dim; d++) {
484 delta[d] = m_nodeInfo[t].position[d] - m_nodeInfo[s].position[d];
485 dist_sq += delta[d] * delta[d];
488 double dist = sqrt(dist_sq);
493 for (
int d = 0; d < Dim; d++) {
494 sum_f[d] += f * delta[d] / dist;
499 for (
int d = 0; d < Dim; d++) {
500 m_nodeInfo[s].force[d] = m_nodeInfo[s].force[d] + sum_f[d] / sum_ddf;
509 double maxDispl = 0.0;
512 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
513 double displ_sq = 0.0;
515 for (
int d = 0; d < Dim; d++) {
516 double displ = m_nodeInfo[v].force[d] / m_nodeInfo[v].force_prime;
517 m_nodeInfo[v].position[d] += displ;
518 displ_sq += displ * displ;
522 if (maxDispl < displ_sq) {
526 Logger::slout() <<
"sqrt(maxDispl)=" << sqrt(maxDispl) << std::endl;
527 return sqrt(maxDispl);
533 double maxDispl = 0.0;
536 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
537 double displ_sq = 0.0;
539 for (
int d = 0; d < Dim; d++) {
540 double displ = m_nodeInfo[v].force[d] * timeStep;
541 m_nodeInfo[v].position[d] += displ;
542 displ_sq += displ * displ;
546 if (maxDispl < displ_sq) {
551 Logger::slout() <<
"sqrt(maxDispl)=" << sqrt(maxDispl) << std::endl;
552 return sqrt(maxDispl);
558 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
560 for (
int d = 0; d < Dim; d++) {
561 m_nodeInfo[v].force[d] = 0.0;
563 m_nodeInfo[v].force_prime = 0.0;
569template<
typename RepForceFunc,
bool>
576 computeRepForces(repForceFunc);
582 return moveNodes(m_defaultTimeStep);
586template<
typename RepForceFunc>
587void DTreeEmbedder<Dim>::doIterations(
int numIterations,
double epsilon, RepForceFunc repForceFunc)
590 double maxDisplacement = epsilon;
593 for (
int i = 0; i < numIterations && maxDisplacement >= epsilon; ++i) {
595 maxDisplacement = doIteration(repForceFunc);
600template<
typename RepForceFunc>
601void DTreeEmbedder<Dim>::doIterationsAdaptive(
int numIterations,
double epsilon, RepForceFunc repForceFunc)
603 int iterationsUsed = 0;
606 double maxTimeStep = 1.0;
607 double timeStep = m_defaultTimeStep;
614 double maxDisplacement = 100000000.0;
617 double lastMaxDisplacement = 0.0;
620 for (
int i = 0; i < numIterations && maxDisplacement >= epsilon; ++i) {
625 computeRepForces(repForceFunc);
631 maxDisplacement = moveNodes(timeStep);
635 if (maxDisplacement < lastMaxDisplacement * t) {
637 timeStep = std::min(timeStep / t, maxTimeStep);
638 }
else if (maxDisplacement > lastMaxDisplacement / t) {
639 timeStep = timeStep * t;
643 lastMaxDisplacement = maxDisplacement;
649 Logger::slout() <<
"IterationsUsed: " << iterationsUsed <<
" of " << numIterations <<
" energy: " << lastMaxDisplacement << std::endl;
660template<
typename RepForceFunc,
typename AttrForceFunc,
bool UseForcePrime>
662 RepForceFunc repForceFunc, AttrForceFunc attrForceFunc) {
663 if (m_graph.numberOfNodes() < 2) {
667 int numIterationsUsed = 0;
669 <<
"doIterationsNewton: V = " << m_graph.numberOfNodes()
670 <<
" E = " << m_graph.numberOfEdges() <<
" Iterations " << numIterations << std::endl;
673 double maxDisplacement = 10000.0;
676 for (
int i = 0; i < numIterations && maxDisplacement > epsilon; ++i) {
682 computeRepForces<RepForceFunc, UseForcePrime>(repForceFunc);
685 computeEdgeForces<AttrForceFunc, UseForcePrime>(attrForceFunc);
689 maxDisplacement = moveNodesByForcePrime();
691 maxDisplacement = moveNodes(0.1);
695 Logger::slout() <<
"Needed " << numIterationsUsed <<
" of " << numIterations << std::endl;
699template<
typename RepForceFunc,
typename AttrForceFunc>
701 RepForceFunc repForceFunc, AttrForceFunc attrForceFunc) {
702 doIterationsTempl<RepForceFunc, AttrForceFunc, false>(numIterations, epsilon, repForceFunc,
707template<
typename RepForceFunc,
typename AttrForceFunc>
709 RepForceFunc repForceFunc, AttrForceFunc attrForceFunc) {
710 doIterationsTempl<RepForceFunc, AttrForceFunc, true>(numIterations, epsilon, repForceFunc,
720 for (
int d = 0; d < Dim; d++) {
721 bboxMin[d] = bboxMax[d] = position(m_graph.firstEdge(), d);
725 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
726 for (
int d = 0; d < Dim; d++) {
727 bboxMin[d] = std::min(bboxMin[d], position(v, d));
728 bboxMax[d] = std::max(bboxMax[d], position(v, d));
733 for (
int d = 0; d < Dim; d++) {
734 delta[d] = -(bboxMin[d] + bboxMax[d]) * 0.5;
737 for (
node v = m_graph.firstNode(); v; v = v->
succ()) {
738 for (
int d = 0; d < Dim; d++) {
739 setPosition(v, d, delta[d]);
746 for (
node v = m_graph.firstNode(); v; v = v->succ()) {
747 for (
int d = 0; d < Dim; d++) {
748 setPosition(v, d, position(v, d) * scaleFactor);
755 return m_nodeInfo[v].position[d];
760 m_nodeInfo[v].position[d] = coord;
765 return m_nodeInfo[v].mass;
770 m_nodeInfo[v].mass = mass;
780 m_edgeWeight[e] = weight;
785 return m_edgeWeight[e];
Includes declaration of graph class.
Contains logging functionality.
adjEntry succ() const
Returns the successor in the adjacency list.
Class for the representation of edges.
Data type for general directed graphs (adjacency list representation).
int numberOfNodes() const
Returns the number of nodes in the graph.
node firstNode() const
Returns the first node in the list of all nodes.
static std::ostream & slout(Level level=Level::Default)
stream for logging-output (global)
Class for the representation of nodes.
int degree() const
Returns the degree of the node (indegree + outdegree).
node succ() const
Returns the successor in the list of all nodes.
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
void centerNodesAt(double centerBBox[Dim])
computes the bounding box and all nodes are translated such that bbox center is at centerBBox
const Graph & m_graph
the graph
NodeArray< NodeInfo > m_nodeInfo
node states of all nodes
void doIterationsNewton(int numIterations, double epsilon, RepForceFunc repForceFunc, AttrForceFunc attrForceFunc)
void setMass(node v, double mass)
sets the mass of a node v
virtual ~DTreeEmbedder()
destructor
DTreeEmbedder(const Graph &graph)
constructor with a given graph, allocates memory and does initialization
void computeEdgeForces(AttrForceFunc attrForceFunc)
computes the edge forces for one iteration
void computeRepForces(ForceFunc forceFunc)
computes the repulsive forces
void setPosition(node v, int d, double coord)
sets the d-th coordinate of node v to coord
double moveNodesByForcePrime()
void doIterationsTempl(int numIterations, double epsilon, RepForceFunc repForceFunc, AttrForceFunc attrForceFunc)
does multiple iterations using the given repulsive force function
void resetForces()
sets the forces of all nodes to 0
void doIterationsStandard(int numIterations, double epsilon, RepForceFunc repForceFunc, AttrForceFunc attrForceFunc)
double position(node v, int d) const
returns the d-th coordinate of node v
const Graph & graph() const
returns the graph
double moveNodes(double timeStep)
moves the nodes by the computed force vector
DTreeForce< Dim > * m_pTreeForce
the tree force approx
void computeRepForcesExact(ForceFunc forceFunc)
computes the repulsive forces for one iteration in O(n^2)
EdgeArray< double > m_edgeWeight
the weight of the edges
void computeRepForcesApprox(ForceFunc forceFunc)
uses the tree code to approximate the repulsive forces in O(nlogn) for one iteration
double mass(node v) const
returns the mass of node v
double edgeWeight(edge e) const
returns the edge weight
int m_maxNumNodesExactRepForces
void setEdgeWeight(edge e, double weight)
sets the weight of an edge
void scaleNodes(double scaleFactor)
changes the position of nodes according to a given scale factor
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
RegisteredArray for nodes, edges and adjEntries of a graph.
AdjElement * adjEntry
The type of adjacency entries.
NodeElement * node
The type of nodes.
The namespace for all OGDF objects.
double mass
the mass of this node
double force[Dim]
the forces on a node
double position[Dim]
position of a node
double force_prime
sum of the derivs