Added knot_desc to knotkit.h/knot_tables.cpp. Resurrected MPI

support.  mpimain.cpp set up to tabulate Kh and steenrod squares.
This commit is contained in:
Cotton Seed 2012-04-11 17:51:14 -04:00
parent 80a531db68
commit 56e3070bc4
6 changed files with 598 additions and 1 deletions

View File

@ -3,6 +3,7 @@ BISON = /opt/local/bin/bison
FLEX = /opt/local/bin/flex FLEX = /opt/local/bin/flex
# CXX = g++ # CXX = g++
# CXX = mpic++
CXX = clang++ -fno-color-diagnostics --stdlib=libc++ --std=c++11 CXX = clang++ -fno-color-diagnostics --stdlib=libc++ --std=c++11
INCLUDES = -I/opt/local/include -I. INCLUDES = -I/opt/local/include -I.
@ -58,6 +59,9 @@ gss: gss.o $(COMMON_OBJS)
main: main.o $(COMMON_OBJS) main: main.o $(COMMON_OBJS)
$(CXX) $(LDFLAGS) -o main $^ $(LIBS) $(CXX) $(LDFLAGS) -o main $^ $(LIBS)
mpimain: mpimain.o mpi_aux.o $(COMMON_OBJS)
$(CXX) $(LDFLAGS) -o main $^ $(LIBS)
testlib: testlib.o $(COMMON_OBJS) testlib: testlib.o $(COMMON_OBJS)
$(CXX) $(LDFLAGS) -o testlib $^ $(CXX) $(LDFLAGS) -o testlib $^
@ -108,4 +112,6 @@ realclean: clean
$(LIB_OBJS): $(LIB_HEADERS) $(LIB_OBJS): $(LIB_HEADERS)
$(ALGEBRA_OBJS): $(ALGEBRA_HEADERS) $(LIB_HEADERS) $(ALGEBRA_OBJS): $(ALGEBRA_HEADERS) $(LIB_HEADERS)
$(KNOTKIT_OBJS) main.o gss.o: $(KNOTKIT_HEADERS) $(ALGEBRA_HEADERS) $(LIB_HEADERS) $(KNOTKIT_OBJS) main.o mpimain.o gss.o: $(KNOTKIT_HEADERS) $(ALGEBRA_HEADERS) $(LIB_HEADERS)
mpimain.o mpi_aux.o: mpi_aux.h

View File

@ -499,6 +499,13 @@ mt_links (unsigned n, bool alternating)
return mt_nonalternating[n - 1]; return mt_nonalternating[n - 1];
} }
unsigned
mt_links (unsigned n)
{
assert (between (1, n, 14));
return mt_alternating[n - 1] + mt_nonalternating[n - 1];
}
dt_code dt_code
mt_link (unsigned n, bool alternating, unsigned k) mt_link (unsigned n, bool alternating, unsigned k)
{ {
@ -535,6 +542,19 @@ mt_link (unsigned n, bool alternating, unsigned k)
return dt_code (buf2, buf); return dt_code (buf2, buf);
} }
dt_code
mt_link (unsigned n, unsigned k)
{
assert (between (1, n, 16));
assert (k >= 1);
unsigned na = mt_links (n, 1);
if (k <= na)
return mt_link (n, 1, k);
else
return mt_link (n, 0, k - na);
}
planar_diagram planar_diagram
torus_knot (unsigned n_strands, unsigned n_shifts) torus_knot (unsigned n_strands, unsigned n_shifts)
{ {
@ -728,3 +748,132 @@ mutant_knot_groups (unsigned n)
return r; return r;
} }
knot_diagram
knot_desc::diagram () const
{
switch (t)
{
case ROLFSEN:
return knot_diagram (rolfsen_knot (i, j));
case HTW:
return knot_diagram (htw_knot (i, j));
case HTW_ALT:
return knot_diagram (htw_knot (i, 1, j));
case HTW_NONALT:
return knot_diagram (htw_knot (i, 0, j));
case MT:
return knot_diagram (mt_link (i, j));
case MT_ALT:
return knot_diagram (mt_link (i, 1, j));
case MT_NONALT:
return knot_diagram (mt_link (i, 0, j));
case TORUS:
return knot_diagram (torus_knot (i, j));
default: abort ();
}
}
std::string
knot_desc::name () const
{
char buf[1000];
switch (t)
{
case ROLFSEN:
sprintf (buf, "%d_%d", i, j);
break;
case HTW:
{
unsigned na = htw_knots (i, 1);
if (j <= na)
sprintf (buf, "%da%d", i, j);
else
sprintf (buf, "%dn%d", i, j - na);
}
break;
case HTW_ALT:
sprintf (buf, "%da%d", i, j);
break;
case HTW_NONALT:
sprintf (buf, "%dn%d", i, j);
break;
case MT:
{
unsigned na = mt_links (i, 1);
if (j <= na)
sprintf (buf, "L%da%d", i, j);
else
sprintf (buf, "L%dn%d", i, j - na);
}
break;
case MT_ALT:
sprintf (buf, "L%da%d", i, j);
break;
case MT_NONALT:
sprintf (buf, "L%dn%d", i, j);
break;
case TORUS:
sprintf (buf, "T(%d, %d)", i, j);
break;
default: abort ();
}
return buf;
}
unsigned
knot_desc::table_crossing_knots () const
{
switch (t)
{
case ROLFSEN:
return rolfsen_crossing_knots (i);
case HTW:
return htw_knots (i);
case HTW_ALT:
return htw_knots (i, 1);
case HTW_NONALT:
return htw_knots (i, 0);
case MT:
return mt_links (i);
case MT_ALT:
return mt_links (i, 1);
case MT_NONALT:
return mt_links (i, 0);
default: abort ();
}
}
knot_desc::knot_desc (reader &r)
{
int x;
read (r, x);
t = (table)x;
read (r, i);
read (r, j);
}
void
knot_desc::write_self (writer &w) const
{
write (w, (int)t);
write (w, i);
write (w, j);
}

View File

@ -23,6 +23,74 @@ class knot_diagram;
#include <steenrod_square.h> #include <steenrod_square.h>
#include <spanning_tree_complex.h> #include <spanning_tree_complex.h>
class knot_desc
{
public:
enum table
{
NONE,
ROLFSEN,
HTW,
HTW_ALT,
HTW_NONALT,
MT,
MT_ALT,
MT_NONALT,
TORUS,
};
table t;
unsigned i;
unsigned j;
public:
knot_desc () : t(NONE) { }
knot_desc (table t_, unsigned i_, unsigned j_)
: t(t_), i(i_), j(j_)
{ }
knot_desc (const knot_desc &desc)
: t(desc.t), i(desc.i), j(desc.j)
{ }
knot_desc (reader &r);
~knot_desc () { }
knot_desc &operator = (const knot_desc &desc)
{
t = desc.t;
i = desc.i;
j = desc.j;
return *this;
}
bool operator == (const knot_desc &desc) const
{
return t == desc.t && i == desc.i && j == desc.j;
}
bool operator < (const knot_desc &desc) const
{
if ((int)t < (int)desc.t)
return 1;
else if ((int)t > (int)desc.t)
return 0;
if (i < desc.i)
return 1;
else if (i > desc.i)
return 0;
return j < desc.j;
}
knot_diagram diagram () const;
std::string name () const;
unsigned table_crossing_knots () const;
void write_self (writer &w) const;
void show_self () const { printf ("%s", name ().c_str ()); }
void display_self () const { show_self (); newline (); }
};
unsigned rolfsen_crossing_knots (unsigned n); unsigned rolfsen_crossing_knots (unsigned n);
planar_diagram rolfsen_knot (unsigned n, unsigned k); planar_diagram rolfsen_knot (unsigned n, unsigned k);
@ -33,7 +101,10 @@ dt_code htw_knot (unsigned n, bool alternating, unsigned k);
dt_code htw_knot (unsigned n, unsigned k); dt_code htw_knot (unsigned n, unsigned k);
unsigned mt_links (unsigned n, bool alternating); unsigned mt_links (unsigned n, bool alternating);
unsigned mt_links (unsigned n);
dt_code mt_link (unsigned n, bool alternating, unsigned k); dt_code mt_link (unsigned n, bool alternating, unsigned k);
dt_code mt_link (unsigned n, unsigned k);
planar_diagram torus_knot (unsigned n_strands, unsigned n_shifts); planar_diagram torus_knot (unsigned n_strands, unsigned n_shifts);

133
mpi_aux.cpp Normal file
View File

@ -0,0 +1,133 @@
#include <mpi.h>
#include <mpi_aux.h>
// #include <knotkit.h>
#define DATATAG 1
void
comm_init (int *argc, char ***argv)
{
MPI_Init (argc, argv);
}
void
comm_finalize ()
{
MPI_Finalize ();
}
int
self_rank ()
{
int node;
MPI_Comm_rank (MPI_COMM_WORLD, &node);
return node;
}
int
num_tasks ()
{
int ntasks;
MPI_Comm_size (MPI_COMM_WORLD, &ntasks);
return ntasks;
}
void
send_int (int v, int dest)
{
MPI_Send (&v, 1, MPI_INT, dest, DATATAG, MPI_COMM_WORLD);
}
void
send_string (const char *s, int dest)
{
int n = strlen (s);
MPI_Send (&n, 1, MPI_INT, dest, DATATAG, MPI_COMM_WORLD);
MPI_Send ((void *)s, n, MPI_CHAR, dest, DATATAG, MPI_COMM_WORLD);
}
void
send_string (const std::string &s, int dest)
{
send_string (s.c_str (), dest);
}
int
recv_int (int *src)
{
int v;
MPI_Status status;
MPI_Recv (&v, /* message buffer */
1, /* one data item */
MPI_INT, /* of type int */
MPI_ANY_SOURCE, /* receive from any sender */
MPI_ANY_TAG, /* any type of message */
MPI_COMM_WORLD, /* default communicator */
&status); /* info about the received message */
if (src)
*src = status.MPI_SOURCE;
return v;
}
std::string
recv_string (int *src)
{
int n;
MPI_Status status;
MPI_Recv (&n, /* message buffer */
1, /* one data item */
MPI_INT, /* of type int */
MPI_ANY_SOURCE, /* receive from any sender */
MPI_ANY_TAG, /* any type of message */
MPI_COMM_WORLD, /* default communicator */
&status); /* info about the received message */
char *s = new char[n + 1];
MPI_Recv (s, /* message buffer */
n, /* one data item */
MPI_CHAR, /* of type int */
status.MPI_SOURCE, /* receive from any sender */
MPI_ANY_TAG, /* any type of message */
MPI_COMM_WORLD, /* default communicator */
&status); /* info about the received message */
if (src)
*src = status.MPI_SOURCE;
s[n] = '\0';
std::string s_std (s);
delete [] s;
return s_std;
}
#if 0
void
send_htw_knot (unsigned n, bool alternating, unsigned k, int dest)
{
int data[3];
data[0] = (int)n;
data[1] = (int)alternating;
data[2] = (int)k;
MPI_Send (&data, 3, MPI_INT, dest, DATATAG, MPI_COMM_WORLD);
}
knot_diagram
recv_knot (int *src)
{
int data[3];
MPI_Status status;
MPI_Recv (&data, /* message buffer */
3, /* one data item */
MPI_INT, /* of type int */
MPI_ANY_SOURCE, /* receive from any sender */
MPI_ANY_TAG, /* any type of message */
MPI_COMM_WORLD, /* default communicator */
&status); /* info about the received message */
if (src)
*src = status.MPI_SOURCE;
dt_code k = htw_knot ((unsigned)data[0],
(bool)data[1],
(unsigned)data[2]);
return knot_diagram (k);
}
#endif

20
mpi_aux.h Normal file
View File

@ -0,0 +1,20 @@
void comm_init (int *argc, char ***argv);
void comm_finalize ();
int self_rank ();
int num_tasks ();
void send_int (int v, int dest);
void send_string (const char *s, int dest);
void send_string (const std::string &s, int dest);
void send_htw_knot (unsigned n, bool alternating, unsigned k, int dest);
int recv_int (int *src);
knot_diagram recv_knot (int *src);
std::string recv_string (int *src);
inline int recv_int () { return recv_int (0); }
knot_diagram recv_knot () { return recv_knot (0); }
std::string recv_string () { return recv_string (0); }

218
mpimain.cpp Normal file
View File

@ -0,0 +1,218 @@
#include <knotkit.h>
#include <mpi.h>
#include <mpi_aux.h>
#define CMD_DO 1
#define CMD_DIE 2
void
master ()
{
basedvector<knot_desc, 1> work;
work.append (knot_desc (TORUS, 0, 0));
for (int a = 1; a >= 0; a --)
for (unsigned i = 1; i <= 10; i ++)
for (unsigned j = 1; j <= rolfsen_crossing_knots (i); j += 4000)
{
work.append (knot_desc (ROLFSEN, i, j));
}
for (int a = 1; a >= 0; a --)
for (unsigned i = 1; i <= 14; i ++)
for (unsigned j = 1; j <= htw_knots (i); j += 4000)
{
work.append (knot_desc (HTW, i, j));
}
for (int a = 1; a >= 0; a --)
for (unsigned i = 1; i <= 13; i ++)
for (unsigned j = 1; j <= mt_links (i); j += 4000)
{
work.append (knot_desc (MT, i, j));
}
int ntasks = num_tasks ();
assert (work.size () > ntasks);
set<unsigned> active;
for (int rank = 1; rank < ntasks && work.size () > 0; rank ++)
{
send_int (CMD_DO, rank);
knot_desc desc = work.pop ();
send_int ((int)desc.t);
send_int ((int)desc.i);
send_int ((int)desc.j);
active.push (rank);
}
while (work.size () > 0)
{
int rank;
int dummy = recv_int (&rank);
send_int (CMD_DO, rank);
knot_desc desc = work.pop ();
send_int ((int)desc.t);
send_int ((int)desc.i);
send_int ((int)desc.j);
}
while (active.card () > 0)
{
int rank;
int dummy = recv_int (&rank);
active -= rank;
}
for (int rank = 1; rank < ntasks; rank ++)
{
send_int (CMD_DIE, rank);
}
}
void
compute_kh_sq (map<knot_desc,
triple<multivariate_laurentpoly<Z>,
multivariate_laurentpoly<Z>,
multivariate_laurentpoly<Z> > > &knot_kh_sq,
knot_desc &desc)
{
knot_diagram kd = desc.diagram ();
unsigned rank = self_rank ();
printf ("[% 2d] %s\n", rank, kd.name.c_str ());
fflush (stdout);
cube<Z2> c (kd);
mod_map<Z2> d = c.compute_d (1, 0, 0, 0, 0);
chain_complex_simplifier<Z2> s (c.khC, d, 1);
steenrod_square sq (c, d, s);
mod_map<Z2> sq1 = sq.sq1 ();
mod_map<Z2> sq2 = sq.sq2 ();
assert (sq1.compose (sq1) == 0);
assert (sq2.compose (sq2) + sq1.compose (sq2).compose (sq1) == 0);
multivariate_laurentpoly<Z> P = s.new_C->free_poincare_polynomial ();
ptr<const free_submodule<Z2> > sq1_im = sq1.image ();
multivariate_laurentpoly<Z> sq1_P = sq1_im->free_poincare_polynomial ();
ptr<const free_submodule<Z2> > sq2_im = sq2.image ();
multivariate_laurentpoly<Z> sq2_P = sq2_im->free_poincare_polynomial ();
knot_kh_sq.push (desc,
triple<multivariate_laurentpoly<Z>,
multivariate_laurentpoly<Z>,
multivariate_laurentpoly<Z> > (P, sq1_P, sq2_P));
}
void
slave ()
{
int rank = self_rank ();
for (;;)
{
int cmd = recv_int ();
switch (cmd)
{
case CMD_DO:
{
knot_desc desc;
desc.t = (knot_desc::table)recv_int ();
desc.i = (knot_desc::table)recv_int ();
desc.j = (knot_desc::table)recv_int ();
map<knot_desc,
triple<multivariate_laurentpoly<Z>,
multivariate_laurentpoly<Z>,
multivariate_laurentpoly<Z> > > knot_kh_sq;
char buf[1000];
if (desc.t == TORUS)
{
sprintf (buf, "T.dat");
for (unsigned t = 3; t <= 16; t ++) // twists
for (unsigned s = 2; s <= t; s ++) // strands
{
if ((s - 1) * t > 16)
continue;
desc.i = s;
desc.j = t;
compute_kh_sq (knot_kh_sq, desc);
}
}
else
{
unsigned j0 = desc.j;
assert (desc.t == knot_desc::HTW || desc.t == knot_desc::MT);
sprintf (buf, "%c%d.dat",
desc.t == knot_desc::HTW ? 'K' : 'L',
j0);
for (unsigned j = j0;
j <= std::min (j0 + 4000,
desc.table_crossing_knots ());
j ++)
{
desc.j = j;
compute_kh_sq (knot_kh_sq, desc);
}
}
{
writer w (buf);
write (w, kh_knot_map);
}
send_int (0, 0);
}
break;
case CMD_DIE:
return;
}
}
}
int
main (int argc, char **argv)
{
comm_init (&argc, &argv);
int rank = self_rank (),
ntasks = num_tasks ();
printf ("[% 2d] alive\n", rank);
fflush (stdout);
if (rank == 0)
{
printf ("ntasks = %d\n", ntasks);
fflush (stdout);
master ();
}
else
slave ();
comm_finalize ();
return 0;
}