Home
|
Course Outline
|
Lectures
|
Homework
|
Files
2 2
3 0 1 => 3 0 1
4 4
which corresponds to the permutation 1234 -> 1234 of nearest
neighbor sites,
2 3
3 0 1 => 4 0 2
4 1
which corresponds to the permutation 1234 -> 2341 of nearest
neighbor sites,
2 4
3 0 1 => 1 0 3
4 2
which corresponds to the permutation 1234 -> 3412 of nearest
neighbor sites,
2 1
3 0 1 => 2 0 4
4 3
which corresponds to the permutation 1234 -> 4321 of nearest
neighbor sites,
2 3
3 0 1 => 2 0 4
4 1
which corresponds to the permutation 1234 -> 4123 of nearest
neighbor sites,
2 4
3 0 1 => 3 0 1
4 2
which corresponds to the permutation 1234 -> 1432 of nearest
neighbor sites,
2 1
3 0 1 => 4 0 2
4 3
which corresponds to the permutation 1234 -> 2143 of nearest
neighbor sites,
2 2
3 0 1 => 1 0 3
4 4
which corresponds to the permutation 1234 -> 3214 of nearest
neighbor sites.
Technically, this group of transformations is the "dihedral group" D4.
If (x, y) is the coordinate of any lattice point, these transformations take it into points with coordinates given in the following table:
It is easy to see that these transformations applied to a walk or polymer will not "break" any of the polymer bonds, i.e., the walk or polymer is transformed rigidly. Note that if we consider polymers related by these transformations to be physical objects confined to a plane, then two polymers related by rotations are physically identical or isomorphic, whereas two polymers that can only be related by a mirror reflection are said to be enantiomorphic. Here is an example of enantiomorphic polymers with N = 4 related by transformation #8:
1. 2. 3. 4. 5. 6. 7. 8. x x y -x -y -y x y -x y y -x -y x -x -y x y
o--o o--o
| |
o o
| |
o--o o--o
Should the random choice for a new head location be the "tail site" (which would be possible for chains of an odd number of steps sufficiently longer than those illustrated in Fig. 1), that would not preclude the move because the tail necessarily moves away as the head moves in.
One could, on the other hand, design a tail-phobic algorithm:
This algorithm would in fact not be able to generate the double cul-de-sac. If one started with the double cul-de-sac, then the polymer would "oscillate" indefinitely with the head and tail interchanging positions with each move.
The following applet, which is generated by the program DoubleCulDeSac.java, demonstrates that the double cul-de-sac polymer can in fact be obtained by the tail-philic reptation algorithm:
Here is the code which generates this applet:
// DoubleCulDeSac.java
import comphys.graphics.*;
public class DoubleCulDeSac extends Animation {
int N = 19; // number of links in chain
int[] xMonomer; // x coordinates of monomers
int[] yMonomer; // y coordinates of monomers
int polymerNumber;
// polymer configuration in Fig. 12.7
int[] dx = {0, -1, 0, -1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, -1, 0, -1, 0};
int[] dy = {1, 0, -1, 0, -1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 1, 0, 1, 0, -1};
boolean doubleCulDeSac () {
boolean found = false;
for (int xDir = -1; xDir < 2; xDir += 2) {
for (int yDir = -1; yDir < 2; yDir += 2) {
for (int i = 0; i < N; i++) {
found = xMonomer[i + 1] - xMonomer[i] == dx[i] * xDir
&& yMonomer[i + 1] - yMonomer[i] == dy[i] * yDir;
if (!found)
break;
}
if (!found) {
for (int i = 0; i < N; i++) {
found = xMonomer[i + 1] - xMonomer[i] == dy[i] * yDir
&& yMonomer[i + 1] - yMonomer[i] == dx[i] * xDir;
if (!found)
break;
}
}
if (found)
break;
}
if (found)
break;
}
return found;
}
void initial () {
if (xMonomer == null) {
xMonomer = new int[N + 1];
yMonomer = new int[N + 1];
}
// initial polymer staircase
xMonomer[N] = N / 2 - 1;
yMonomer[N] = N / 2;
for (int i = N; i > 0; i--) {
if (i % 2 == 0) { // step up
xMonomer[i - 1] = xMonomer[i];
yMonomer[i - 1] = yMonomer[i] + 1;
} else { // step right
xMonomer[i - 1] = xMonomer[i] + 1;
yMonomer[i - 1] = yMonomer[i];
}
}
polymerNumber = -N;
}
void makeDoubleCulDeSac () {
// remove tail
for (int i = 0; i < N; i++) {
xMonomer[i] = xMonomer[i + 1];
yMonomer[i] = yMonomer[i + 1];
}
// add monomer at head
int i = N + polymerNumber;
xMonomer[N] = xMonomer[N - 1] + dx[i];
yMonomer[N] = yMonomer[N - 1] + dy[i];
}
boolean occupied (int x, int y) {
for (int n = 0; n < N; n++)
if (xMonomer[n] == x && yMonomer[n] == y)
return true;
return false;
}
void reptate () {
// save tail monomer position
int xTail = xMonomer[0];
int yTail = yMonomer[0];
// remove tail
for (int i = 0; i < N; i++) {
xMonomer[i] = xMonomer[i + 1];
yMonomer[i] = yMonomer[i + 1];
}
// try to add a monomer at head in one of two possible positions
int xTry = xMonomer[N - 1];
int yTry = yMonomer[N - 1];
if (xTry == xMonomer[N - 2]) { // left or right at random
if (Math.random() < 0.5)
xTry += 1;
else
xTry -= 1;
} else { // up or down at random
if (Math.random() < 0.5)
yTry += 1;
else
yTry -= 1;
}
if (!occupied(xTry, yTry)) {
xMonomer[N] = xTry;
yMonomer[N] = yTry;
} else { // interchange head and tail in original configuration
xMonomer[N] = xTail;
yMonomer[N] = yTail;
for (int i = 0; i <= (N - 1) / 2; i++) {
xTail = xMonomer[i];
yTail = yMonomer[i];
xMonomer[i] = xMonomer[N - i - 1];
yMonomer[i] = yMonomer[N - i - 1];
xMonomer[N - i - 1] = xTail;
yMonomer[N - i - 1] = yTail;
}
}
}
class Lattice extends Plot {
Lattice () {
setSize(400, 400);
setBackground("white");
}
String[] colors = {"red", "green", "blue",
"cyan", "magenta", "yellow"};
int pbc (int i) {
while (i < 0)
i += N;
while (i >= N)
i -= N;
return i;
}
public void paint () {
clear();
setWindow(-0.5, N - 0.5, -0.5, N - 0.5);
// draw the lattice points
setColor("black");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
plotPoint(i, j);
}
}
// draw the polymer
double r = 0.15;
int x = pbc(xMonomer[0]);
int y = pbc(yMonomer[0]);
floodCircle(x - r, x + r, y - r, y + r);
for (int i = 0; i < N; i++) {
int c = i;
while (c >= colors.length)
c -= colors.length;
setColor(colors[c]);
x = pbc(xMonomer[i]);
y = pbc(yMonomer[i]);
int x1 = pbc(xMonomer[i + 1]);
int y1 = pbc(yMonomer[i + 1]);
if (Math.abs(x - x1) <= 1 && Math.abs(y - y1) <= 1)
plotLine(x, y, x1, y1);
}
}
}
boolean foundDoubleCulDeSac;
int doubleCulDeSacs;
class Output extends Plot {
Output () {
setSize(400, 20);
setBackground("blue");
}
public void paint () {
clear();
setWindow(0, 100, 0, 3);
setColor("white");
plotString("Polymer number: " + polymerNumber, 5, 1);
if (foundDoubleCulDeSac)
plotStringLeft("Found double cul-de-sac #"
+ doubleCulDeSacs, 95, 1);
}
}
Lattice lattice;
Output output;
public void init () {
initial();
add(lattice = new Lattice());
add(output = new Output());
addControlPanel();
}
public void step () {
if (polymerNumber < 0)
makeDoubleCulDeSac();
else
reptate();
++polymerNumber;
if (foundDoubleCulDeSac = doubleCulDeSac()) {
++doubleCulDeSacs;
stopAnimation();
}
lattice.repaint();
output.repaint();
}
public void reset () {
initial();
lattice.repaint();
foundDoubleCulDeSac = false;
doubleCulDeSacs = 0;
output.repaint();
}
public static void main (String[] args) {
DoubleCulDeSac dcds = new DoubleCulDeSac();
dcds.frame("Double Cul-de-sac", 430, 520);
}
}