40 namespace 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>
90 void computeEdgeForcesSq();
99 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);
197 template<
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;
229 template<
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];
254 template<
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);
292 template<
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);
327 template<
typename ForceFunc,
bool UseForcePrime>
329 if (m_graph.numberOfNodes() <= m_maxNumNodesExactRepForces) {
330 computeRepForcesExact<ForceFunc, UseForcePrime>(forceFunc);
332 computeRepForcesApprox<ForceFunc, UseForcePrime>(forceFunc);
338 template<
typename ForceFunc>
341 if (m_graph.numberOfNodes() <= m_maxNumNodesExactRepForces) {
342 computeRepForcesExactNewton(forceFunc);
344 computeRepForcesApproxNewton(forceFunc);
350 template<
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;
406 template<
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;
456 void 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;
569 template<
typename RepForceFunc,
bool>
576 computeRepForces(repForceFunc);
582 return moveNodes(m_defaultTimeStep);
586 template<
typename RepForceFunc>
587 void 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);
600 template<
typename RepForceFunc>
601 void 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;
660 template<
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;
699 template<
typename RepForceFunc,
typename AttrForceFunc>
701 RepForceFunc repForceFunc, AttrForceFunc attrForceFunc) {
702 doIterationsTempl<RepForceFunc, AttrForceFunc, false>(numIterations, epsilon, repForceFunc,
707 template<
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];