DNA分裂算法

时间:2014-06-24 09:01:19

标签: c algorithm statistics

我想知道温度和结合能对DNA分裂的影响。 我用一个简单的一维步行来描述DNA聚合物的位置。我已经设置了初始条件,使它们重叠。初始位置是自我避免和单向随机游走。该聚合物具有128个单体,每个单元的位置由阵列a [0-127]和b [0-127]给出。存在与两个单体处于相同位置相关的能量E(我已经采取-1)。所有其他间隔距离都没有能量。 现在我使用Metropolis算法使聚合物达到平衡。 我随机选择了一种单体(256种中的单体)并将其翻转。翻转已被定义为

  

a [i] = a [i + 1] + a [i-1] + a [1]

这将是' b'而不是'在第二种聚合物的情况下。 当然,如果选择最终聚合物,则翻转将由

定义
  

a [127] = 2 * a [126] + a [127]

应该注意的是,由于翻转,位置将变为2,0或-2。

现在,大都会算法表明,如果由于翻转没有能量变化,则总是允许翻转(例如,如果已经分离的单体更进一步或者如果分离的单体更接近但不完全在一起)。 当能量变化为负时,即在翻转两个单体后,也总是允许翻转。 当存在正能量变化时,即当最初两个单体在一起但在翻转之后它们分开然后翻转被接受的概率为

  

powf(M_E,(E / T))

暂时T也被视为1。

该算法被多次迭代,直到达到关于末端分离距离的平衡,即b [127] -a [127]。 为了生成随机数,我使用了一个我在代码中定义的drand函数。既然有人告诉我它可能不是一个非常好的随机数生成器,我也尝试使用函数ran2,我刚刚将它复制到代码中而没有它的工作方式。

无论如何,现在我的问题是平衡距离远远高于应有的距离。理想情况下,我被告知最终应该是0或者2和4。不仅如此,这是不太可能的。但我的代码经常给出22,30之类的值等等。 有人能告诉我有什么问题吗?请随时要求进一步澄清。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define IM1 2147483563
#define IM2 2147483399
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NTAB 32
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)


float drand()
{
    float f, r, randmax;
    r = rand();
    randmax = RAND_MAX;
    f = r/(randmax+1);
    return(f);
}

double ran2(long *idum)
{
    int j;
    long k;
    static long idum2=123456789;
    static long iy=0;
    static long iv[NTAB];
    double temp;

    if (*idum <= 0)           /* Initialize. */
    {
        if (-(*idum) < 1) *idum=1;  /*Be sure to prevent idum = 0. */
        else *idum = -(*idum);
        idum2=(*idum);
        for (j=NTAB+7; j>=0; j--) /* Load the shuffle table (after 8 warm-ups).*/
        {
            k=(*idum)/IQ1;
            *idum=IA1*(*idum-k*IQ1)-k*IR1;
            if (*idum < 0) *idum += IM1;
            if (j < NTAB) iv[j] = *idum;
        }
        iy=iv[0];
    }
    k=(*idum)/IQ1; /* Start here when not initializing.*/
    *idum=IA1*(*idum-k*IQ1)-k*IR1; /* Compute idum=(IA1*idum) % IM1 without
                                   overflows by Schrage's method. */
    if (*idum < 0) *idum += IM1;
    k=idum2/IQ2;
    idum2=IA2*(idum2-k*IQ2)-k*IR2; /* Compute idum2=(IA2*idum) % IM2 likewise. */
    if (idum2 < 0) idum2 += IM2;
    j=iy/NDIV;                    /* Will be in the range 0..NTAB-1. */
    iy=iv[j]-idum2;               /* Here idum is shuffled, idum and idum2 are
                                  combined to generate output. */
    iv[j] = *idum;
    if (iy < 1) iy += IMM1;
    if ((temp=AM*iy) > RNMX)
        return RNMX;               /* Because users don't expect endpoint values. */
    else return temp;
}


int main()
{
    int a[128],b[128]; /*array defining position of polymer*/
    long int i, j;          /* integers defined for iteration purposes*/
    int r;             /* The rth random monomer of the polymer while conducting the MC algorithm*/
    int x;             /* The new position of the monomer if it overcomes the probability*/
    float E = -1;       /* Energy associated with overlapping monomers*/
    float T = 1;       /* Temperature*/
    int t;              /*separation between final monomers*/
    long idum = time(NULL);
    srand (time(NULL)); /*set seed for the random number*/
    a[0]=0;
    b[0]=0;
    for (i=1; i<128; i++) /*Defining a random but overlapping initial position for the strands*/
    {
        if (ran2(&idum)<0.5)
        {
            a[i]=a[i-1]+1;
            b[i]=a[i];
        }
        else
        {
            a[i]=b[i]=a[i-1]-1;
            b[i]=a[i];
        }
    }

    /* Following is the metropolis algorithm*/
    for (j=1; j<1000000; j=j+1)
    {
        r = floor(ran2(&idum)*128);
        if (ran2(&idum)<0.5)
        {
            if (r<=126)
            {
                x=a[r+1]+a[r-1]-a[r];
                if (x==b[r])
                {
                    a[r]=x;
                }
                else if (x==b[r]-2)
                {
                    if (ran2(&idum)<powf(M_E,(E/T)))
                    {
                        a[r]=x;
                    }
                }
                else if (x<b[r]-2)
                {
                    a[r]=x;
                }
            }
            else if (r==127)
            {
                x=2*a[126]-a[127];
                if (x==b[127])
                {
                    a[127]=x;
                }
                else if (x==b[127]-2)
                {
                    if (ran2(&idum)<powf(M_E,(E/T)))
                    {
                        a[127]=x;
                    }
                }
                else if (x<b[127]-2)
                {
                    a[127]=x;
                }
            }
        }
        else
        {
            if (r<=126)
            {
                x=b[r+1]+b[r-1]-b[r];
                if (x==a[r])
                {
                    b[r]=x;
                }
                else if (x==a[r]+2)
                {
                    if (ran2(&idum)<powf(M_E,(E/T)))
                    {
                        b[r]=x;
                    }
                }
                else if (x>a[r]+2)
                {
                    b[r]=x;
                }
            }
            else if (r==127)
            {
                x=2*b[126]-b[127];
                if (x==a[127])
                {
                    b[127]=x;
                }
                else if (x==a[127]+2)
                {
                    if (ran2(&idum)<powf(M_E,(E/T)))
                    {
                        b[127]=x;
                    }
                }
                else if (x>a[127]+2)
                {
                    b[127]=x;
                }
            }
        }
        t = b[127]-a[127];
        if (j%(25600)==0)
        {
            printf("%d\n", t);
        }
    }
    printf("%f\n", powf(M_E,(E/T)));
    return 0;
}

1 个答案:

答案 0 :(得分:1)

我意识到自己犯了什么错误。 首先是冗余b [i] = a [i]。 可能不是错误,但我确信编码习惯不好。 第二。我的朋友指出我的算法称为r = 0的值,而我的代码使用[r-1]然后会给出随机数。我实际上必须确保r不接受0的值,因为两种聚合物的第一单体都保持固定在0。

最后也是最重要的问题,在陈述中

else if (x==a[127]+2)
            {
                if (ran2(&idum)<powf(M_E,(E/T)))
                {
                    b[127]=x;
                }
            }

else if (x==b[r]-2)
            {
                if (ran2(&idum)<powf(M_E,(E/T)))
                {
                    a[r]=x;
                }

并且r = 127但你明白了。 实际上我认为单体只能从与另一个聚合物相邻的位置翻转,即a [r] = b [r]到新位置x。但是经过多次迭代之后,还会出现[r] + 4 = b [r]并且它进入新位置x,其中x == b [r] -2。 并且这种翻转总是被接受,而不是具有小于1的概率。 所以代码的新行应该是

else if (x==b[r]-2)
            {
                if (a[r]==b[r])
                {
                    if (drand()<powf(M_E,(E/T)))
                {
                    a[r]=x;
                }
                }
                else
                {
                    a[r]=x;
                }
            }

其他3例同样如此。这兼顾了两种可能性。代码工作正常。 感谢所有那些经历过这么长时间的问题而痛苦的人。