int igraph_random_sample_alga(igraph_vector_t *res, igraph_integer_t l, igraph_integer_t h, igraph_integer_t length) { igraph_real_t N=h-l+1; igraph_real_t n=length; igraph_real_t top=N-n; igraph_real_t Nreal=N; igraph_real_t S=0; igraph_real_t V, quot; l=l-1; while (n>=2) { V=RNG_UNIF01(); S=1; quot=top/Nreal; while (quot>V) { S+=1; top=-1.0+top; Nreal=-1.0+Nreal; quot=(quot*top)/Nreal; } l+=S; igraph_vector_push_back(res, l); /* allocated */ Nreal=-1.0+Nreal; n=-1+n; } S=floor(round(Nreal)*RNG_UNIF01()); l+=S+1; igraph_vector_push_back(res, l); /* allocated */ return 0; }
int splicing_reassign_samples(const splicing_matrix_t *matches, const splicing_vector_int_t *match_order, const splicing_vector_t *psi, int noiso, splicing_vector_int_t *result) { int noreads = splicing_matrix_ncol(matches); int i, w; double *prev, *curr; double rand, sumpsi; int noValid; int *order=VECTOR(*match_order); splicing_vector_t cumsum; splicing_vector_int_t validIso; SPLICING_CHECK(splicing_vector_init(&cumsum, noiso)); SPLICING_FINALLY(splicing_vector_destroy, &cumsum); SPLICING_CHECK(splicing_vector_int_init(&validIso, noiso)); SPLICING_FINALLY(splicing_vector_int_destroy, &validIso); SPLICING_CHECK(splicing_vector_int_resize(result, noreads)); if (noreads == 0) { return 0; } prev = curr = &MATRIX(*matches, 0, order[0]); CUMSUM(); for (i=0; i<noreads; i++) { curr = &MATRIX(*matches, 0, order[i]); /* Maybe we need to update the cumulative sum */ if (memcmp(prev, curr, sizeof(double)*noiso) != 0) { CUMSUM(); } if (noValid == 0) { VECTOR(*result)[order[i]] = -1; } else if (noValid == 1) { VECTOR(*result)[order[i]] = VECTOR(validIso)[0]; } else if (noValid == 2) { rand = RNG_UNIF01() * sumpsi; w = (rand < VECTOR(cumsum)[0]) ? VECTOR(validIso)[0] : VECTOR(validIso)[1]; VECTOR(*result)[order[i]] = w; } else { /* Draw */ rand = RNG_UNIF01() * sumpsi; /* TODO: Binary search for interval, if many classes */ for (w=0; rand > VECTOR(cumsum)[w]; w++) ; VECTOR(*result)[order[i]] = VECTOR(validIso)[w]; } prev=curr; } splicing_vector_int_destroy(&validIso); splicing_vector_destroy(&cumsum); SPLICING_FINALLY_CLEAN(2); return 0; }
double igraph_exp_rand(void) { /* q[k-1] = sum(log(2)^k / k!) k=1,..,n, */ /* The highest n (here 8) is determined by q[n-1] = 1.0 */ /* within standard precision */ const double q[] = { 0.6931471805599453, 0.9333736875190459, 0.9888777961838675, 0.9984959252914960, 0.9998292811061389, 0.9999833164100727, 0.9999985691438767, 0.9999998906925558, 0.9999999924734159, 0.9999999995283275, 0.9999999999728814, 0.9999999999985598, 0.9999999999999289, 0.9999999999999968, 0.9999999999999999, 1.0000000000000000 }; double a, u, ustar, umin; int i; a = 0.; /* precaution if u = 0 is ever returned */ u = RNG_UNIF01(); while(u <= 0.0 || u >= 1.0) u = RNG_UNIF01(); for (;;) { u += u; if (u > 1.0) break; a += q[0]; } u -= 1.; if (u <= q[0]) return a + u; i = 0; ustar = RNG_UNIF01(); umin = ustar; do { ustar = RNG_UNIF01(); if (ustar < umin) umin = ustar; i++; } while (u > q[i]); return a + umin * q[0]; }
int splicing_drift_proposal(int mode, const splicing_vector_t *psi, const splicing_vector_t *alpha, double sigma, const splicing_vector_t *otherpsi, const splicing_vector_t *otheralpha, int noiso, splicing_vector_t *respsi, splicing_vector_t *resalpha, double *ressigma, double *resscore) { switch (mode) { case 0: /* init */ { SPLICING_CHECK(splicing_vector_resize(respsi, noiso)); SPLICING_CHECK(splicing_vector_resize(resalpha, noiso-1)); if (noiso != 2) { int i; for (i=0; i<noiso; i++) { VECTOR(*respsi)[i] = 1.0/noiso; } for (i=0; i<noiso-1; i++) { VECTOR(*resalpha)[i] = 1.0/(noiso-1); } *ressigma = 0.05; } else { VECTOR(*respsi)[0] = RNG_UNIF01(); VECTOR(*respsi)[1] = 1 - VECTOR(*respsi)[0]; VECTOR(*resalpha)[0] = 0.0; VECTOR(*resalpha)[1] = 0.0; *ressigma = 0.05; } } break; case 1: /* propose */ { int len=noiso-1; double sumpsi=0.0; SPLICING_CHECK(splicing_vector_reserve(respsi, len+1)); SPLICING_CHECK(splicing_mvrnorm(alpha, sigma, resalpha, len)); SPLICING_CHECK(splicing_logit_inv(resalpha, respsi, len)); sumpsi = splicing_vector_sum(respsi); SPLICING_CHECK(splicing_vector_resize(respsi, len+1)); VECTOR(*respsi)[len] = 1-sumpsi; } break; case 2: /* score */ SPLICING_CHECK(splicing_mvplogisnorm(psi, otheralpha, sigma, noiso-1, resscore)); break; } return 0; }
int igraph_dot_product_game(igraph_t *graph, const igraph_matrix_t *vecs, igraph_bool_t directed) { igraph_integer_t nrow=igraph_matrix_nrow(vecs); igraph_integer_t ncol=igraph_matrix_ncol(vecs); int i, j; igraph_vector_t edges; igraph_bool_t warned_neg=0, warned_big=0; IGRAPH_VECTOR_INIT_FINALLY(&edges, 0); RNG_BEGIN(); for (i = 0; i < ncol; i++) { int from=directed ? 0 : i+1; igraph_vector_t v1; igraph_vector_view(&v1, &MATRIX(*vecs, 0, i), nrow); for (j = from; j < ncol; j++) { igraph_real_t prob; igraph_vector_t v2; if (i==j) { continue; } igraph_vector_view(&v2, &MATRIX(*vecs, 0, j), nrow); igraph_lapack_ddot(&v1, &v2, &prob); if (prob < 0 && ! warned_neg) { warned_neg=1; IGRAPH_WARNING("Negative connection probability in " "dot-product graph"); } else if (prob > 1 && ! warned_big) { warned_big=1; IGRAPH_WARNING("Greater than 1 connection probability in " "dot-product graph"); IGRAPH_CHECK(igraph_vector_push_back(&edges, i)); IGRAPH_CHECK(igraph_vector_push_back(&edges, j)); } else if (RNG_UNIF01() < prob) { IGRAPH_CHECK(igraph_vector_push_back(&edges, i)); IGRAPH_CHECK(igraph_vector_push_back(&edges, j)); } } } RNG_END(); igraph_create(graph, &edges, ncol, directed); igraph_vector_destroy(&edges); IGRAPH_FINALLY_CLEAN(1); return 0; }
int igraph_sample_sphere_volume(igraph_integer_t dim, igraph_integer_t n, igraph_real_t radius, igraph_bool_t positive, igraph_matrix_t *res) { igraph_integer_t i, j; /* Arguments are checked by the following call */ IGRAPH_CHECK(igraph_sample_sphere_surface(dim, n, radius, positive, res)); RNG_BEGIN(); for (i = 0; i < n; i++) { igraph_real_t *col=&MATRIX(*res, 0, i); igraph_real_t U=pow(RNG_UNIF01(), 1.0/dim); for (j = 0; j < dim; j++) { col[j] *= U; } } RNG_END(); return 0; }
double igraph_rbinom(double nin, double pp) { /* FIXME: These should become THREAD_specific globals : */ static double c, fm, npq, p1, p2, p3, p4, qn; static double xl, xll, xlr, xm, xr; static double psave = -1.0; static int nsave = -1; static int m; double f, f1, f2, u, v, w, w2, x, x1, x2, z, z2; double p, q, np, g, r, al, alv, amaxp, ffm, ynorm; int i,ix,k, n; if (!R_FINITE(nin)) ML_ERR_return_NAN; n = floor(nin + 0.5); if (n != nin) ML_ERR_return_NAN; if (!R_FINITE(pp) || /* n=0, p=0, p=1 are not errors <TSL>*/ n < 0 || pp < 0. || pp > 1.) ML_ERR_return_NAN; if (n == 0 || pp == 0.) return 0; if (pp == 1.) return n; p = fmin(pp, 1. - pp); q = 1. - p; np = n * p; r = p / q; g = r * (n + 1); /* Setup, perform only when parameters change [using static (globals): */ /* FIXING: Want this thread safe -- use as little (thread globals) as possible */ if (pp != psave || n != nsave) { psave = pp; nsave = n; if (np < 30.0) { /* inverse cdf logic for mean less than 30 */ qn = pow(q, (double) n); goto L_np_small; } else { ffm = np + p; m = ffm; fm = m; npq = np * q; p1 = (int)(2.195 * sqrt(npq) - 4.6 * q) + 0.5; xm = fm + 0.5; xl = xm - p1; xr = xm + p1; c = 0.134 + 20.5 / (15.3 + fm); al = (ffm - xl) / (ffm - xl * p); xll = al * (1.0 + 0.5 * al); al = (xr - ffm) / (xr * q); xlr = al * (1.0 + 0.5 * al); p2 = p1 * (1.0 + c + c); p3 = p2 + c / xll; p4 = p3 + c / xlr; } } else if (n == nsave) { if (np < 30.0) goto L_np_small; } /*-------------------------- np = n*p >= 30 : ------------------- */ repeat { u = RNG_UNIF01() * p4; v = RNG_UNIF01(); /* triangular region */ if (u <= p1) { ix = xm - p1 * v + u; goto finis; } /* parallelogram region */ if (u <= p2) { x = xl + (u - p1) / c; v = v * c + 1.0 - fabs(xm - x) / p1; if (v > 1.0 || v <= 0.) continue; ix = x; } else { if (u > p3) { /* right tail */ ix = xr - log(v) / xlr; if (ix > n) continue; v = v * (u - p3) * xlr; } else {/* left tail */ ix = xl + log(v) / xll; if (ix < 0) continue; v = v * (u - p2) * xll; } } /* determine appropriate way to perform accept/reject test */ k = abs(ix - m); if (k <= 20 || k >= npq / 2 - 1) { /* explicit evaluation */ f = 1.0; if (m < ix) { for (i = m + 1; i <= ix; i++) f *= (g / i - r); } else if (m != ix) { for (i = ix + 1; i <= m; i++) f /= (g / i - r); } if (v <= f) goto finis; } else { /* squeezing using upper and lower bounds on log(f(x)) */ amaxp = (k / npq) * ((k * (k / 3. + 0.625) + 0.1666666666666) / npq + 0.5); ynorm = -k * k / (2.0 * npq); alv = log(v); if (alv < ynorm - amaxp) goto finis; if (alv <= ynorm + amaxp) { /* stirling's formula to machine accuracy */ /* for the final acceptance/rejection test */ x1 = ix + 1; f1 = fm + 1.0; z = n + 1 - fm; w = n - ix + 1.0; z2 = z * z; x2 = x1 * x1; f2 = f1 * f1; w2 = w * w; if (alv <= xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) + (ix - m) * log(w * p / (x1 * q)) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.) goto finis; } } } L_np_small: /*---------------------- np = n*p < 30 : ------------------------- */ repeat { ix = 0; f = qn; u = RNG_UNIF01(); repeat { if (u < f) goto finis; if (ix > 110) break; u -= f; ix++; f *= (g / ix - r); } } finis: if (psave > 0.5) ix = n - ix; return (double)ix; }
double igraph_rpois(double mu) { /* Factorial Table (0:9)! */ const double fact[10] = { 1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880. }; /* These are static --- persistent between calls for same mu : */ static int l, m; static double b1, b2, c, c0, c1, c2, c3; static double pp[36], p0, p, q, s, d, omega; static double big_l;/* integer "w/o overflow" */ static double muprev = 0., muprev2 = 0.;/*, muold = 0.*/ /* Local Vars [initialize some for -Wall]: */ double del, difmuk= 0., E= 0., fk= 0., fx, fy, g, px, py, t, u= 0., v, x; double pois = -1.; int k, kflag, big_mu, new_big_mu = FALSE; if (!R_FINITE(mu)) ML_ERR_return_NAN; if (mu <= 0.) return 0.; big_mu = mu >= 10.; if(big_mu) new_big_mu = FALSE; if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */ if (big_mu) { new_big_mu = TRUE; /* Case A. (recalculation of s,d,l because mu has changed): * The poisson probabilities pk exceed the discrete normal * probabilities fk whenever k >= m(mu). */ muprev = mu; s = sqrt(mu); d = 6. * mu * mu; big_l = floor(mu - 1.1484); /* = an upper bound to m(mu) for all mu >= 10.*/ } else { /* Small mu ( < 10) -- not using normal approx. */ /* Case B. (start new table and calculate p0 if necessary) */ /*muprev = 0.;-* such that next time, mu != muprev ..*/ if (mu != muprev) { muprev = mu; m = imax2(1, (int) mu); l = 0; /* pp[] is already ok up to pp[l] */ q = p0 = p = exp(-mu); } repeat { /* Step U. uniform sample for inversion method */ u = RNG_UNIF01(); if (u <= p0) return 0.; /* Step T. table comparison until the end pp[l] of the pp-table of cumulative poisson probabilities (0.458 > ~= pp[9](= 0.45792971447) for mu=10 ) */ if (l != 0) { for (k = (u <= 0.458) ? 1 : imin2(l, m); k <= l; k++) if (u <= pp[k]) return (double)k; if (l == 35) /* u > pp[35] */ continue; } /* Step C. creation of new poisson probabilities p[l..] and their cumulatives q =: pp[k] */ l++; for (k = l; k <= 35; k++) { p *= mu / k; q += p; pp[k] = q; if (u <= q) { l = k; return (double)k; } } l = 35; } /* end(repeat) */ }/* mu < 10 */ } /* end {initialize persistent vars} */ /* Only if mu >= 10 : ----------------------- */ /* Step N. normal sample */ g = mu + s * igraph_norm_rand();/* norm_rand() ~ N(0,1), standard normal */ if (g >= 0.) { pois = floor(g); /* Step I. immediate acceptance if pois is large enough */ if (pois >= big_l) return pois; /* Step S. squeeze acceptance */ fk = pois; difmuk = mu - fk; u = RNG_UNIF01(); /* ~ U(0,1) - sample */ if (d * u >= difmuk * difmuk * difmuk) return pois; } /* Step P. preparations for steps Q and H. (recalculations of parameters if necessary) */ if (new_big_mu || mu != muprev2) { /* Careful! muprev2 is not always == muprev because one might have exited in step I or S */ muprev2 = mu; omega = M_1_SQRT_2PI / s; /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite * approximations to the discrete normal probabilities fk. */ b1 = one_24 / mu; b2 = 0.3 * b1 * b1; c3 = one_7 * b1 * b2; c2 = b2 - 15. * c3; c1 = b1 - 6. * b2 + 45. * c3; c0 = 1. - b1 + 3. * b2 - 15. * c3; c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */ } if (g >= 0.) { /* 'Subroutine' F is called (kflag=0 for correct return) */ kflag = 0; goto Step_F; } repeat { /* Step E. Exponential Sample */ E = igraph_exp_rand(); /* ~ Exp(1) (standard exponential) */ /* sample t from the laplace 'hat' (if t <= -0.6744 then pk < fk for all mu >= 10.) */ u = 2 * RNG_UNIF01() - 1.; t = 1.8 + fsign(E, u); if (t > -0.6744) { pois = floor(mu + s * t); fk = pois; difmuk = mu - fk; /* 'subroutine' F is called (kflag=1 for correct return) */ kflag = 1; Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */ if (pois < 10) { /* use factorials from table fact[] */ px = -mu; py = pow(mu, pois) / fact[(int)pois]; } else { /* Case pois >= 10 uses polynomial approximation a0-a7 for accuracy when advisable */ del = one_12 / fk; del = del * (1. - 4.8 * del * del); v = difmuk / fk; if (fabs(v) <= 0.25) px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v + a0) - del; else /* |v| > 1/4 */ px = fk * log(1. + v) - difmuk - del; py = M_1_SQRT_2PI / sqrt(fk); } x = (0.5 - difmuk) / s; x *= x;/* x^2 */ fx = -0.5 * x; fy = omega * (((c3 * x + c2) * x + c1) * x + c0); if (kflag > 0) { /* Step H. Hat acceptance (E is repeated on rejection) */ if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E)) break; } else /* Step Q. Quotient acceptance (rare case) */ if (fy - u * fy <= py * exp(px - fx)) break; }/* t > -.67.. */ } return pois; }
int igraph_random_sample(igraph_vector_t *res, igraph_integer_t l, igraph_integer_t h, igraph_integer_t length) { igraph_real_t N=h-l+1; igraph_real_t n=length; int retval; igraph_real_t nreal=length; igraph_real_t ninv=1.0/nreal; igraph_real_t Nreal=N; igraph_real_t Vprime; igraph_real_t qu1=-n+1+N; igraph_real_t qu1real=-nreal+1.0+Nreal; igraph_real_t negalphainv=-13; igraph_real_t threshold=-negalphainv*n; igraph_real_t S; igraph_vector_clear(res); IGRAPH_CHECK(igraph_vector_reserve(res, length)); RNG_BEGIN(); Vprime=exp(log(RNG_UNIF01())*ninv); while (n>1 && threshold < N) { igraph_real_t X, U; igraph_real_t limit, t; igraph_real_t negSreal, y1, y2, top, bottom; igraph_real_t nmin1inv=1.0/(-1.0+nreal); while (1) { while(1) { X=Nreal*(-Vprime+1.0); S=floor(X); if (S==0) { S=1; } if (S <qu1) { break; } Vprime = exp(log(RNG_UNIF01())*ninv); } U=RNG_UNIF01(); negSreal=-S; y1=exp(log(U*Nreal/qu1real)*nmin1inv); Vprime=y1*(-X/Nreal+1.0)*(qu1real/(negSreal+qu1real)); if (Vprime <= 1.0) { break; } y2=1.0; top=-1.0+Nreal; if (-1+n > S) { bottom=-nreal+Nreal; limit=-S+N; } else { bottom=-1.0+negSreal+Nreal; limit=qu1; } for (t=-1+N; t>=limit; t--) { y2=(y2*top)/bottom; top=-1.0+top; bottom=-1.0+bottom; } if (Nreal/(-X+Nreal) >= y1*exp(log(y2)*nmin1inv)) { Vprime=exp(log(RNG_UNIF01())*nmin1inv); break; } Vprime=exp(log(RNG_UNIF01())*ninv); } l+=S; igraph_vector_push_back(res, l); /* allocated */ N=-S+(-1+N); Nreal=negSreal+(-1.0+Nreal); n=-1+n; nreal=-1.0+nreal; ninv=nmin1inv; qu1=-S+qu1; qu1real=negSreal+qu1real; threshold=threshold+negalphainv; } if (n>1) { retval=igraph_random_sample_alga(res, l, h, n); } else { retval=0; S=floor(N*Vprime); l+=S; igraph_vector_push_back(res, l); /* allocated */ } RNG_END(); return retval; }
int splicing_miso_trinity(const splicing_matrix_t *match_matrix, const splicing_vector_int_t *isolen, int readLength, int noIterations, int noBurnIn, int noLag, const splicing_vector_t *hyperp, splicing_matrix_t *samples, splicing_vector_t *logLik, splicing_matrix_t *class_templates, splicing_vector_t *class_counts, splicing_vector_int_t *assignment, splicing_miso_rundata_t *rundata) { double acceptP, cJS, pJS, sigma; int noiso = splicing_matrix_nrow(match_matrix); int noReads = splicing_matrix_ncol(match_matrix); splicing_vector_int_t *myass=assignment, vass; splicing_vector_t vpsi, vpsiNew, valpha, valphaNew, *psi=&vpsi, *psiNew=&vpsiNew, *alpha=&valpha, *alphaNew=&valphaNew; int noSamples = (noIterations - noBurnIn + 1) / noLag; int i, m, lagCounter=0, noS=0; splicing_vector_int_t match_order; splicing_vector_int_t effisolen; splicing_vector_t isoscores; if ( (class_templates ? 1 : 0) + (class_counts ? 1 : 0) == 1) { SPLICING_ERROR("Only one of `class_templates' and `class_counts' is " "given", SPLICING_EINVAL); } rundata->noIso=noiso; rundata->noIters=noIterations; rundata->noBurnIn=noBurnIn; rundata->noLag=noLag; rundata->noAccepted = rundata->noRejected = 0; if (assignment) { SPLICING_CHECK(splicing_vector_int_resize(myass, noReads)); splicing_vector_int_null(myass); } else { myass=&vass; SPLICING_CHECK(splicing_vector_int_init(myass, noReads)); SPLICING_FINALLY(splicing_vector_int_destroy, myass); } SPLICING_CHECK(splicing_vector_init(&vpsi, noiso)); SPLICING_FINALLY(splicing_vector_destroy, &vpsi); SPLICING_CHECK(splicing_vector_init(&vpsiNew, noiso)); SPLICING_FINALLY(splicing_vector_destroy, &vpsiNew); SPLICING_CHECK(splicing_vector_init(&valpha, noiso-1)); SPLICING_FINALLY(splicing_vector_destroy, &valpha); SPLICING_CHECK(splicing_vector_init(&valphaNew, noiso-1)); SPLICING_FINALLY(splicing_vector_destroy, &valphaNew); SPLICING_CHECK(splicing_vector_int_init(&match_order, noReads)); SPLICING_FINALLY(splicing_vector_int_destroy, &match_order); SPLICING_CHECK(splicing_order_matches(match_matrix, &match_order)); if (class_templates && class_counts) { SPLICING_CHECK(splicing_i_miso_classes(match_matrix, &match_order, class_templates, class_counts, /*bin_class_templates=*/ 0, /*bin_class_counts=*/ 0)); } SPLICING_CHECK(splicing_vector_int_init(&effisolen, noiso)); SPLICING_FINALLY(splicing_vector_int_destroy, &effisolen); SPLICING_CHECK(splicing_vector_init(&isoscores, noiso)); SPLICING_FINALLY(splicing_vector_destroy, &isoscores); for (i=0; i<noiso; i++) { int l=VECTOR(*isolen)[i]-readLength+1; VECTOR(effisolen)[i] = l > 0 ? l : 0; VECTOR(isoscores)[i] = -log((double) l); } SPLICING_CHECK(splicing_matrix_resize(samples, noiso, noSamples)); SPLICING_CHECK(splicing_vector_resize(logLik, noSamples)); /* Initialize Psi(0) randomly */ SPLICING_CHECK(splicing_drift_proposal(/* mode= */ 0, 0, 0, 0, 0, 0, noiso, psi, alpha, &sigma, 0)); SPLICING_CHECK(splicing_drift_proposal(/* mode= */ 1, psi, alpha, sigma, 0, 0, noiso, psi, alpha, 0, 0)); /* Initialize assignments of reads */ SPLICING_CHECK(splicing_reassign_samples(match_matrix, &match_order, psi, noiso, myass)); /* foreach Iteration m=1, ..., M do */ for (m=0; m < noIterations; m++) { SPLICING_CHECK(splicing_drift_proposal(/* mode= */ 1, psi, alpha, sigma, 0, 0, noiso, psiNew, alphaNew, 0, 0)); SPLICING_CHECK(splicing_metropolis_hastings_ratio(myass, noReads, psiNew, alphaNew, psi, alpha, sigma, noiso, &effisolen, hyperp, &isoscores, m > 0 ? 1 : 0, &acceptP, &cJS, &pJS)); if (acceptP >= 1 || RNG_UNIF01() < acceptP) { splicing_vector_t *tmp; tmp=psi; psi=psiNew; psiNew=tmp; tmp=alpha; alpha=alphaNew; alphaNew=tmp; cJS = pJS; rundata->noAccepted ++; } else { rundata->noRejected ++; } if (m >= noBurnIn) { if (lagCounter == noLag - 1) { memcpy(&MATRIX(*samples, 0, noS), VECTOR(*psi), noiso * sizeof(double)); VECTOR(*logLik)[noS] = cJS; noS++; lagCounter = 0; } else { lagCounter ++; } } SPLICING_CHECK(splicing_reassign_samples(match_matrix, &match_order, psi, noiso, myass)); } /* for m < noIterations */ splicing_vector_destroy(&isoscores); splicing_vector_int_destroy(&effisolen); splicing_vector_int_destroy(&match_order); splicing_vector_destroy(&valphaNew); splicing_vector_destroy(&valpha); splicing_vector_destroy(&vpsiNew); splicing_vector_destroy(&vpsi); SPLICING_FINALLY_CLEAN(7); if (!assignment) { splicing_vector_int_destroy(myass); SPLICING_FINALLY_CLEAN(1); } return 0; }
int splicing_simulate_reads(const splicing_gff_t *gff, int gene, const splicing_vector_t *expression, int noreads, int readLength, splicing_vector_int_t *isoform, splicing_vector_int_t *position, splicing_strvector_t *cigar, splicing_vector_t *sample_prob) { size_t i, p, noiso, goodiso=0, nogenes; splicing_vector_int_t effisolen; splicing_vector_t sampleprob; double rand, sumpsi=0.0; splicing_vector_int_t exstart, exend, exidx; SPLICING_CHECK(splicing_gff_nogenes(gff, &nogenes)); if (gene < 0 || gene >= nogenes) { SPLICING_ERROR("Invalid gene id", SPLICING_EINVAL); } /* TODO: more error checks */ SPLICING_CHECK(splicing_gff_noiso_one(gff, gene, &noiso)); SPLICING_CHECK(splicing_vector_int_init(&effisolen, noiso)); SPLICING_FINALLY(splicing_vector_int_destroy, &effisolen); SPLICING_CHECK(splicing_vector_init(&sampleprob, noiso)); SPLICING_FINALLY(splicing_vector_destroy, &sampleprob); SPLICING_CHECK(splicing_vector_int_resize(isoform, noreads)); SPLICING_CHECK(splicing_gff_isolength_one(gff, gene, &effisolen)); for (i=0; i<noiso; i++) { int l=VECTOR(effisolen)[i]-readLength+1; VECTOR(effisolen)[i] = l > 0 ? l : 0; VECTOR(sampleprob)[i] = VECTOR(*expression)[i] * VECTOR(effisolen)[i]; if (VECTOR(sampleprob)[i] != 0) { goodiso++; } sumpsi += VECTOR(sampleprob)[i]; } if (goodiso==0) { SPLICING_ERROR("No isoform is possible", SPLICING_FAILURE); } if (sample_prob) { SPLICING_CHECK(splicing_vector_update(sample_prob, &sampleprob)); } for (i=1; i<noiso; i++) { VECTOR(sampleprob)[i] += VECTOR(sampleprob)[i-1]; } for (i=0; i<noreads; i++) { int w; if (noiso==1) { w=0; } else if (noiso==2) { rand = RNG_UNIF01() * sumpsi; w = (rand < VECTOR(sampleprob)[0]) ? 0 : 1; } else { rand = RNG_UNIF01() * sumpsi; for (w=0; rand > VECTOR(sampleprob)[w]; w++) ; } VECTOR(*isoform)[i]=w; } splicing_vector_destroy(&sampleprob); SPLICING_FINALLY_CLEAN(1); /* OK, we have the isoforms, now we need the read positions, these are uniformly sampled from the individual isoforms. */ SPLICING_CHECK(splicing_vector_int_resize(position, noreads)); SPLICING_CHECK(splicing_vector_int_init(&exstart, 0)); SPLICING_FINALLY(splicing_vector_int_destroy, &exstart); SPLICING_CHECK(splicing_vector_int_init(&exend, 0)); SPLICING_FINALLY(splicing_vector_int_destroy, &exend); SPLICING_CHECK(splicing_vector_int_init(&exidx, 0)); SPLICING_FINALLY(splicing_vector_int_destroy, &exidx); SPLICING_CHECK(splicing_gff_exon_start_end(gff, &exstart, &exend, &exidx, gene)); /* Positions in isoform coordinates first */ for (i=0; i<noreads; i++) { int iso=VECTOR(*isoform)[i]; int len=VECTOR(effisolen)[iso]; VECTOR(*position)[i]=RNG_INTEGER(1, len); } /* Translate isoform coordinates to genomic coordintes */ /* TODO: some of this is already calculated */ SPLICING_CHECK(splicing_iso_to_genomic(gff, gene, isoform, /*converter=*/ 0, position)); /* CIGAR strings */ splicing_strvector_clear(cigar); SPLICING_CHECK(splicing_strvector_reserve(cigar, noreads)); for (i=0; i<noreads; i++) { char tmp[1000], *tmp2=tmp; int iso=VECTOR(*isoform)[i]; size_t rs=VECTOR(*position)[i]; int ex=0; int rl=readLength; for (ex=VECTOR(exidx)[iso]; VECTOR(exend)[ex] < rs; ex++) ; while (VECTOR(exend)[ex] < rs+rl-1) { tmp2 += snprintf(tmp2, sizeof(tmp)/sizeof(char)-(tmp2-tmp)-1, "%iM%iN", (int) (VECTOR(exend)[ex]-rs+1), (int) (VECTOR(exstart)[ex+1]-VECTOR(exend)[ex]-1)); if (tmp2 >= tmp + sizeof(tmp)/sizeof(char)) { SPLICING_ERROR("CIGAR string too long", SPLICING_EINVAL); } rl -= (VECTOR(exend)[ex] - rs + 1); rs = VECTOR(exstart)[ex+1]; ex++; } tmp2 += snprintf(tmp2, sizeof(tmp)/sizeof(char)-(tmp2-tmp)-1, "%iM", rl); if (tmp2 >= tmp + sizeof(tmp)/sizeof(char)) { SPLICING_ERROR("CIGAR string too long", SPLICING_EINVAL); } SPLICING_CHECK(splicing_strvector_append(cigar, tmp)); } splicing_vector_int_destroy(&exidx); splicing_vector_int_destroy(&exend); splicing_vector_int_destroy(&exstart); splicing_vector_int_destroy(&effisolen); SPLICING_FINALLY_CLEAN(4); return 0; }
int splicing_simulate_paired_reads(const splicing_gff_t *gff, int gene, const splicing_vector_t *expression, int noreads, int readLength, const splicing_vector_t *fragmentProb, int fragmentStart, double normalMean, double normalVar, double numDevs, splicing_vector_int_t *isoform, splicing_vector_int_t *position, splicing_strvector_t *cigar, splicing_vector_t *sampleprob) { size_t i, j, noiso, il, nogenes; splicing_vector_t *mysampleprob=sampleprob, vsampleprob; splicing_vector_t px, cpx; double sumpx, sumpsi=0.0; splicing_vector_int_t isolen; int goodiso=0; splicing_vector_int_t exstart, exend, exidx; splicing_vector_t *myfragmentProb=(splicing_vector_t*) fragmentProb, vfragmentProb; int fs, fl; SPLICING_CHECK(splicing_gff_nogenes(gff, &nogenes)); if (gene < 0 || gene >= nogenes) { SPLICING_ERROR("Invalid gene id", SPLICING_EINVAL); } /* TODO: more error checks */ if (!fragmentProb) { myfragmentProb=&vfragmentProb; SPLICING_CHECK(splicing_vector_init(&vfragmentProb, 0)); SPLICING_FINALLY(splicing_vector_destroy, &vfragmentProb); SPLICING_CHECK(splicing_normal_fragment(normalMean, normalVar, numDevs, readLength, myfragmentProb, &fragmentStart)); splicing_vector_scale(myfragmentProb, 1.0/splicing_vector_sum(myfragmentProb)); } il=splicing_vector_size(myfragmentProb); fs=fragmentStart; fl=fragmentStart+il-1; SPLICING_CHECK(splicing_gff_noiso_one(gff, gene, &noiso)); if ( fabs(splicing_vector_sum(myfragmentProb) - 1.0) > 1e-10 ) { SPLICING_ERROR("Fragment length distribution does not sum up to 1", SPLICING_EINVAL); } SPLICING_CHECK(splicing_vector_int_init(&isolen, noiso)); SPLICING_FINALLY(splicing_vector_int_destroy, &isolen); SPLICING_CHECK(splicing_gff_isolength_one(gff, gene, &isolen)); SPLICING_CHECK(splicing_vector_copy(&px, myfragmentProb)); SPLICING_FINALLY(splicing_vector_destroy, &px); SPLICING_CHECK(splicing_vector_init(&cpx, il)); SPLICING_FINALLY(splicing_vector_destroy, &cpx); if (!sampleprob) { mysampleprob=&vsampleprob; SPLICING_CHECK(splicing_vector_init(mysampleprob, noiso)); SPLICING_FINALLY(splicing_vector_destroy, mysampleprob); } else { SPLICING_CHECK(splicing_vector_resize(mysampleprob, noiso)); } for (sumpx=VECTOR(px)[0], i=1; i<il; i++) { VECTOR(px)[i] += VECTOR(px)[i-1]; sumpx += VECTOR(px)[i]; } VECTOR(cpx)[0] = VECTOR(px)[0]; for (i=1; i<il; i++) { VECTOR(cpx)[i] = VECTOR(cpx)[i-1] + VECTOR(px)[i]; } for (i=0; i<noiso; i++) { int ilen=VECTOR(isolen)[i]; int r1= ilen >= fl ? ilen - fl + 1 : 0; int r2= ilen >= fs ? (ilen >= fl ? fl - fs : ilen - fs + 1) : 0; /* int r3= fs - 1; */ double sp=0.0; if (r1 > 0) { sp += r1; } if (r2 > 0) { sp += VECTOR(cpx)[r2-1]; } VECTOR(*mysampleprob)[i] = sp * VECTOR(*expression)[i]; if (VECTOR(*mysampleprob)[i] != 0) { goodiso += 1; } sumpsi += VECTOR(*mysampleprob)[i]; } if (goodiso == 0) { SPLICING_ERROR("No isoform is possible", SPLICING_FAILURE); } for (i=1; i<noiso; i++) { VECTOR(*mysampleprob)[i] += VECTOR(*mysampleprob)[i-1]; } SPLICING_CHECK(splicing_vector_int_resize(isoform, noreads*2)); for (i=0; i<2*noreads; i+=2) { int w; double rand; if (noiso==1) { w=0; } else if (noiso==2) { rand = RNG_UNIF01() * sumpsi; w = (rand < VECTOR(*mysampleprob)[0]) ? 0 : 1; } else { rand = RNG_UNIF01() * sumpsi; for (w=0; rand > VECTOR(*mysampleprob)[w]; w++) ; } VECTOR(*isoform)[i]=VECTOR(*isoform)[i+1]=w; } if (!sampleprob) { splicing_vector_destroy(mysampleprob); SPLICING_FINALLY_CLEAN(1); } else { for (i=noiso-1; i>0; i--) { VECTOR(*mysampleprob)[i] -= VECTOR(*mysampleprob)[i-1]; } } /* We have the isoforms, now get the read positions. */ SPLICING_CHECK(splicing_vector_int_resize(position, noreads*2)); SPLICING_CHECK(splicing_vector_int_init(&exstart, 0)); SPLICING_FINALLY(splicing_vector_int_destroy, &exstart); SPLICING_CHECK(splicing_vector_int_init(&exend, 0)); SPLICING_FINALLY(splicing_vector_int_destroy, &exend); SPLICING_CHECK(splicing_vector_int_init(&exidx, 0)); SPLICING_FINALLY(splicing_vector_int_destroy, &exidx); SPLICING_CHECK(splicing_gff_exon_start_end(gff, &exstart, &exend, &exidx, gene)); /* Positions in isoform coordinates first. These are sampled based on the fragment length distribution. */ for (i=0, j=0; i<noreads; i++) { int iso=VECTOR(*isoform)[2*i]; int ilen=VECTOR(isolen)[iso]; int r1= ilen >= fl ? ilen - fl + 1 : 0; int r2= ilen >= fs ? (ilen >= fl ? fl - fs : ilen - fs + 1) : 0; /* int r3= fs - 1; */ int pos, fragment; double sp=0.0; if (r1 > 0) { sp += r1; } if (r2 > 0) { sp += VECTOR(cpx)[r2-1]; } double rand=RNG_UNIF(0, sp); if (rand < r1) { pos = ceil(rand); } else { int w; rand -= r1; for (w=0; VECTOR(cpx)[w] < rand; w++) ; pos = r1 + r2 - w; } if (pos <= r1) { rand=RNG_UNIF(0, 1.0); } else { rand=RNG_UNIF(0, VECTOR(px)[r1+r2-pos]); } for (fragment=0; VECTOR(px)[fragment] < rand; fragment++) ; fragment += fragmentStart; VECTOR(*position)[j++] = pos; VECTOR(*position)[j++] = pos+fragment-readLength; } /* Translate positions to genomic coordinates */ /* TODO: some of this is already calculated */ SPLICING_CHECK(splicing_iso_to_genomic(gff, gene, isoform, /*converter=*/ 0, position)); /* CIGAR strings */ splicing_strvector_clear(cigar); SPLICING_CHECK(splicing_strvector_reserve(cigar, 2*noreads)); for (j=0; j<2*noreads; j++) { char tmp[1000], *tmp2=tmp; int iso=VECTOR(*isoform)[j]; size_t rs=VECTOR(*position)[j]; int ex=0; int rl=readLength; for (ex=VECTOR(exidx)[iso]; VECTOR(exend)[ex] < rs; ex++) ; while (rs + rl - 1 > VECTOR(exend)[ex]) { tmp2 += snprintf(tmp2, sizeof(tmp)/sizeof(char)-(tmp2-tmp)-1, "%iM%iN", (int) (VECTOR(exend)[ex]-rs+1), (int) (VECTOR(exstart)[ex+1]-VECTOR(exend)[ex]-1)); if (tmp2 >= tmp + sizeof(tmp)/sizeof(char)) { SPLICING_ERROR("CIGAR string too long", SPLICING_EINVAL); } rl -= (VECTOR(exend)[ex] - rs + 1); rs = VECTOR(exstart)[ex+1]; ex++; } tmp2 += snprintf(tmp2, sizeof(tmp)/sizeof(char)-(tmp2-tmp)-1, "%iM", rl); if (tmp2 >= tmp + sizeof(tmp)/sizeof(char)) { SPLICING_ERROR("CIGAR string too long", SPLICING_EINVAL); } SPLICING_CHECK(splicing_strvector_append(cigar, tmp)); } splicing_vector_int_destroy(&exidx); splicing_vector_int_destroy(&exend); splicing_vector_int_destroy(&exstart); splicing_vector_destroy(&cpx); splicing_vector_destroy(&px); splicing_vector_int_destroy(&isolen); SPLICING_FINALLY_CLEAN(6); if (!fragmentProb) { splicing_vector_destroy(myfragmentProb); SPLICING_FINALLY_CLEAN(1); } return 0; }
int igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy, const igraph_vector_t *minz, const igraph_vector_t *maxz) { igraph_integer_t no_nodes=igraph_vcount(graph); igraph_integer_t no_edges=igraph_ecount(graph); igraph_integer_t i; igraph_vector_float_t dispx, dispy, dispz; igraph_real_t temp=start_temp; igraph_real_t difftemp=start_temp / niter; float width=sqrtf(no_nodes), height=width, depth=width; igraph_bool_t conn=1; float C; if (niter < 0) { IGRAPH_ERROR("Number of iterations must be non-negative in " "Fruchterman-Reingold layout", IGRAPH_EINVAL); } if (use_seed && (igraph_matrix_nrow(res) != no_nodes || igraph_matrix_ncol(res) != 3)) { IGRAPH_ERROR("Invalid start position matrix size in " "Fruchterman-Reingold layout", IGRAPH_EINVAL); } if (weight && igraph_vector_size(weight) != igraph_ecount(graph)) { IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL); } if (minx && igraph_vector_size(minx) != no_nodes) { IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL); } if (maxx && igraph_vector_size(maxx) != no_nodes) { IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL); } if (minx && maxx && !igraph_vector_all_le(minx, maxx)) { IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL); } if (miny && igraph_vector_size(miny) != no_nodes) { IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL); } if (maxy && igraph_vector_size(maxy) != no_nodes) { IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL); } if (miny && maxy && !igraph_vector_all_le(miny, maxy)) { IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL); } if (minz && igraph_vector_size(minz) != no_nodes) { IGRAPH_ERROR("Invalid minz vector length", IGRAPH_EINVAL); } if (maxz && igraph_vector_size(maxz) != no_nodes) { IGRAPH_ERROR("Invalid maxz vector length", IGRAPH_EINVAL); } if (minz && maxz && !igraph_vector_all_le(minz, maxz)) { IGRAPH_ERROR("minz must not be greater than maxz", IGRAPH_EINVAL); } igraph_is_connected(graph, &conn, IGRAPH_WEAK); if (!conn) { C = no_nodes * sqrtf(no_nodes); } RNG_BEGIN(); if (!use_seed) { IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3)); for (i=0; i<no_nodes; i++) { igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2; igraph_real_t x2=maxx ? VECTOR(*maxx)[i] : width/2; igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2; igraph_real_t y2=maxy ? VECTOR(*maxy)[i] : height/2; igraph_real_t z1=minz ? VECTOR(*minz)[i] : -depth/2; igraph_real_t z2=maxz ? VECTOR(*maxz)[i] : depth/2; MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); MATRIX(*res, i, 2) = RNG_UNIF(z1, z2); } } IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx); IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy); IGRAPH_CHECK(igraph_vector_float_init(&dispz, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispz); for (i=0; i<niter; i++) { igraph_integer_t v, u, e; /* calculate repulsive forces, we have a special version for unconnected graphs */ igraph_vector_float_null(&dispx); igraph_vector_float_null(&dispy); igraph_vector_float_null(&dispz); if (conn) { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2); float dlen=dx * dx + dy * dy + dz * dz; if (dlen == 0) { dx = RNG_UNIF01() * 1e-9; dy = RNG_UNIF01() * 1e-9; dz = RNG_UNIF01() * 1e-9; dlen = dx * dx + dy * dy + dz * dz; } VECTOR(dispx)[v] += dx/dlen; VECTOR(dispy)[v] += dy/dlen; VECTOR(dispz)[v] += dz/dlen; VECTOR(dispx)[u] -= dx/dlen; VECTOR(dispy)[u] -= dy/dlen; VECTOR(dispz)[u] -= dz/dlen; } } } else { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2); float dlen, rdlen; dlen=dx * dx + dy * dy + dz * dz; if (dlen == 0) { dx = RNG_UNIF01() * 1e-9; dy = RNG_UNIF01() * 1e-9; dz = RNG_UNIF01() * 1e-9; dlen = dx * dx + dy * dy + dz * dz; } rdlen=sqrt(dlen); VECTOR(dispx)[v] += dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[v] += dy * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[v] += dz * (C-dlen * rdlen) / (dlen*C); VECTOR(dispx)[u] -= dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[u] -= dy * (C-dlen * rdlen) / (dlen*C); VECTOR(dispz)[u] -= dz * (C-dlen * rdlen) / (dlen*C); } } } /* calculate attractive forces */ for (e=0; e<no_edges; e++) { /* each edges is an ordered pair of vertices v and u */ igraph_integer_t v=IGRAPH_FROM(graph, e); igraph_integer_t u=IGRAPH_TO(graph, e); igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2); igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0; igraph_real_t dlen=sqrt(dx * dx + dy * dy + dz * dz) * w; VECTOR(dispx)[v] -= (dx * dlen); VECTOR(dispy)[v] -= (dy * dlen); VECTOR(dispz)[v] -= (dz * dlen); VECTOR(dispx)[u] += (dx * dlen); VECTOR(dispy)[u] += (dy * dlen); VECTOR(dispz)[u] += (dz * dlen); } /* limit max displacement to temperature t and prevent from displacement outside frame */ for (v=0; v<no_nodes; v++) { igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dz=VECTOR(dispz)[v] + RNG_UNIF01() * 1e-9; igraph_real_t displen=sqrt(dx * dx + dy * dy + dz * dz); igraph_real_t mx=fabs(dx) < temp ? dx : temp; igraph_real_t my=fabs(dy) < temp ? dy : temp; igraph_real_t mz=fabs(dz) < temp ? dz : temp; if (displen > 0) { MATRIX(*res, v, 0) += (dx / displen) * mx; MATRIX(*res, v, 1) += (dy / displen) * my; MATRIX(*res, v, 2) += (dz / displen) * mz; } if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { MATRIX(*res, v, 0) = VECTOR(*minx)[v]; } if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) { MATRIX(*res, v, 0) = VECTOR(*maxx)[v]; } if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) { MATRIX(*res, v, 1) = VECTOR(*miny)[v]; } if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) { MATRIX(*res, v, 1) = VECTOR(*maxy)[v]; } if (minz && MATRIX(*res, v, 2) < VECTOR(*minz)[v]) { MATRIX(*res, v, 2) = VECTOR(*minz)[v]; } if (maxz && MATRIX(*res, v, 2) > VECTOR(*maxz)[v]) { MATRIX(*res, v, 2) = VECTOR(*maxz)[v]; } } temp -= difftemp; } RNG_END(); igraph_vector_float_destroy(&dispx); igraph_vector_float_destroy(&dispy); igraph_vector_float_destroy(&dispz); IGRAPH_FINALLY_CLEAN(3); return 0; }
int igraph_layout_i_fr(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { igraph_integer_t no_nodes=igraph_vcount(graph); igraph_integer_t no_edges=igraph_ecount(graph); igraph_integer_t i; igraph_vector_float_t dispx, dispy; igraph_real_t temp=start_temp; igraph_real_t difftemp=start_temp / niter; float width=sqrtf(no_nodes), height=width; igraph_bool_t conn=1; float C; igraph_is_connected(graph, &conn, IGRAPH_WEAK); if (!conn) { C = no_nodes * sqrtf(no_nodes); } RNG_BEGIN(); if (!use_seed) { IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); for (i=0; i<no_nodes; i++) { igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2; igraph_real_t x2=maxx ? VECTOR(*maxx)[i] : width/2; igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2; igraph_real_t y2=maxy ? VECTOR(*maxy)[i] : height/2; if (!igraph_finite(x1)) { x1 = -sqrt(no_nodes)/2; } if (!igraph_finite(x2)) { x2 = sqrt(no_nodes)/2; } if (!igraph_finite(y1)) { y1 = -sqrt(no_nodes)/2; } if (!igraph_finite(y2)) { y2 = sqrt(no_nodes)/2; } MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); } } IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx); IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy); for (i=0; i<niter; i++) { igraph_integer_t v, u, e; /* calculate repulsive forces, we have a special version for unconnected graphs */ igraph_vector_float_null(&dispx); igraph_vector_float_null(&dispy); if (conn) { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dlen=dx * dx + dy * dy; if (dlen == 0) { dx = RNG_UNIF01() * 1e-9; dy = RNG_UNIF01() * 1e-9; dlen = dx * dx + dy * dy; } VECTOR(dispx)[v] += dx/dlen; VECTOR(dispy)[v] += dy/dlen; VECTOR(dispx)[u] -= dx/dlen; VECTOR(dispy)[u] -= dy/dlen; } } } else { for (v=0; v<no_nodes; v++) { for (u=v+1; u<no_nodes; u++) { float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); float dlen, rdlen; dlen=dx * dx + dy * dy; if (dlen == 0) { dx = RNG_UNIF(0, 1e-6); dy = RNG_UNIF(0, 1e-6); dlen = dx * dx + dy * dy; } rdlen=sqrt(dlen); VECTOR(dispx)[v] += dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[v] += dy * (C-dlen * rdlen) / (dlen*C); VECTOR(dispx)[u] -= dx * (C-dlen * rdlen) / (dlen*C); VECTOR(dispy)[u] -= dy * (C-dlen * rdlen) / (dlen*C); } } } /* calculate attractive forces */ for (e=0; e<no_edges; e++) { /* each edges is an ordered pair of vertices v and u */ igraph_integer_t v=IGRAPH_FROM(graph, e); igraph_integer_t u=IGRAPH_TO(graph, e); igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0; igraph_real_t dlen=sqrt(dx * dx + dy * dy) * w; VECTOR(dispx)[v] -= (dx * dlen); VECTOR(dispy)[v] -= (dy * dlen); VECTOR(dispx)[u] += (dx * dlen); VECTOR(dispy)[u] += (dy * dlen); } /* limit max displacement to temperature t and prevent from displacement outside frame */ for (v=0; v<no_nodes; v++) { igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9; igraph_real_t displen=sqrt(dx * dx + dy * dy); igraph_real_t mx=fabs(dx) < temp ? dx : temp; igraph_real_t my=fabs(dy) < temp ? dy : temp; if (displen > 0) { MATRIX(*res, v, 0) += (dx / displen) * mx; MATRIX(*res, v, 1) += (dy / displen) * my; } if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { MATRIX(*res, v, 0) = VECTOR(*minx)[v]; } if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) { MATRIX(*res, v, 0) = VECTOR(*maxx)[v]; } if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) { MATRIX(*res, v, 1) = VECTOR(*miny)[v]; } if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) { MATRIX(*res, v, 1) = VECTOR(*maxy)[v]; } } temp -= difftemp; } RNG_END(); igraph_vector_float_destroy(&dispx); igraph_vector_float_destroy(&dispy); IGRAPH_FINALLY_CLEAN(2); return 0; }
int igraph_layout_i_grid_fr(const igraph_t *graph, igraph_matrix_t *res, igraph_bool_t use_seed, igraph_integer_t niter, igraph_real_t start_temp, const igraph_vector_t *weight, const igraph_vector_t *minx, const igraph_vector_t *maxx, const igraph_vector_t *miny, const igraph_vector_t *maxy) { igraph_integer_t no_nodes=igraph_vcount(graph); igraph_integer_t no_edges=igraph_ecount(graph); float width=sqrtf(no_nodes), height=width; igraph_2dgrid_t grid; igraph_vector_float_t dispx, dispy; igraph_real_t temp=start_temp; igraph_real_t difftemp=start_temp / niter; igraph_2dgrid_iterator_t vidit; igraph_integer_t i; const float cellsize=2.0; RNG_BEGIN(); if (!use_seed) { IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2)); for (i=0; i<no_nodes; i++) { igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2; igraph_real_t x2=maxx ? VECTOR(*maxx)[i] : width/2; igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2; igraph_real_t y2=maxy ? VECTOR(*maxy)[i] : height/2; if (!igraph_finite(x1)) { x1 = -sqrt(no_nodes)/2; } if (!igraph_finite(x2)) { x2 = sqrt(no_nodes)/2; } if (!igraph_finite(y1)) { y1 = -sqrt(no_nodes)/2; } if (!igraph_finite(y2)) { y2 = sqrt(no_nodes)/2; } MATRIX(*res, i, 0) = RNG_UNIF(x1, x2); MATRIX(*res, i, 1) = RNG_UNIF(y1, y2); } } /* make grid */ IGRAPH_CHECK(igraph_2dgrid_init(&grid, res, -width/2, width/2, cellsize, -height/2, height/2, cellsize)); IGRAPH_FINALLY(igraph_2dgrid_destroy, &grid); /* place vertices on grid */ for (i=0; i<no_nodes; i++) { igraph_2dgrid_add2(&grid, i); } IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx); IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes)); IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy); for (i=0; i<niter; i++) { igraph_integer_t v, u, e; igraph_vector_float_null(&dispx); igraph_vector_float_null(&dispy); /* repulsion */ igraph_2dgrid_reset(&grid, &vidit); while ( (v=igraph_2dgrid_next(&grid, &vidit)-1) != -1) { while ( (u=igraph_2dgrid_next_nei(&grid, &vidit)-1) != -1) { float dx=MATRIX(*res, v, 0)-MATRIX(*res, u, 0); float dy=MATRIX(*res, v, 1)-MATRIX(*res, u, 1); float dlen=dx * dx + dy * dy; if (dlen < cellsize * cellsize) { VECTOR(dispx)[v] += dx/dlen; VECTOR(dispy)[v] += dy/dlen; VECTOR(dispx)[u] -= dx/dlen; VECTOR(dispy)[u] -= dy/dlen; } } } /* attraction */ for (e=0; e<no_edges; e++) { igraph_integer_t v=IGRAPH_FROM(graph, e); igraph_integer_t u=IGRAPH_TO(graph, e); igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0); igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1); igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0; igraph_real_t dlen=sqrt(dx * dx + dy * dy) * w; VECTOR(dispx)[v] -= (dx * dlen); VECTOR(dispy)[v] -= (dy * dlen); VECTOR(dispx)[u] += (dx * dlen); VECTOR(dispy)[u] += (dy * dlen); } /* update */ for (v=0; v<no_nodes; v++) { igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9; igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9; igraph_real_t displen=sqrt(dx * dx + dy * dy); igraph_real_t mx=fabs(dx) < temp ? dx : temp; igraph_real_t my=fabs(dy) < temp ? dy : temp; if (displen > 0) { MATRIX(*res, v, 0) += (dx / displen) * mx; MATRIX(*res, v, 1) += (dy / displen) * my; } if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { MATRIX(*res, v, 0) = VECTOR(*minx)[v]; } if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) { MATRIX(*res, v, 0) = VECTOR(*maxx)[v]; } if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) { MATRIX(*res, v, 1) = VECTOR(*miny)[v]; } if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) { MATRIX(*res, v, 1) = VECTOR(*maxy)[v]; } } temp -= difftemp; } igraph_vector_float_destroy(&dispx); igraph_vector_float_destroy(&dispy); igraph_2dgrid_destroy(&grid); IGRAPH_FINALLY_CLEAN(3); return 0; }