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:
parent
80a531db68
commit
56e3070bc4
8
Makefile
8
Makefile
@ -3,6 +3,7 @@ BISON = /opt/local/bin/bison
|
||||
FLEX = /opt/local/bin/flex
|
||||
|
||||
# CXX = g++
|
||||
# CXX = mpic++
|
||||
CXX = clang++ -fno-color-diagnostics --stdlib=libc++ --std=c++11
|
||||
|
||||
INCLUDES = -I/opt/local/include -I.
|
||||
@ -58,6 +59,9 @@ gss: gss.o $(COMMON_OBJS)
|
||||
main: main.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o main $^ $(LIBS)
|
||||
|
||||
mpimain: mpimain.o mpi_aux.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o main $^ $(LIBS)
|
||||
|
||||
testlib: testlib.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o testlib $^
|
||||
|
||||
@ -108,4 +112,6 @@ realclean: clean
|
||||
|
||||
$(LIB_OBJS): $(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
|
||||
|
149
knot_tables.cpp
149
knot_tables.cpp
@ -499,6 +499,13 @@ mt_links (unsigned n, bool alternating)
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
torus_knot (unsigned n_strands, unsigned n_shifts)
|
||||
{
|
||||
@ -728,3 +748,132 @@ mutant_knot_groups (unsigned n)
|
||||
|
||||
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);
|
||||
}
|
||||
|
71
knotkit.h
71
knotkit.h
@ -23,6 +23,74 @@ class knot_diagram;
|
||||
#include <steenrod_square.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);
|
||||
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);
|
||||
|
||||
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, unsigned k);
|
||||
|
||||
planar_diagram torus_knot (unsigned n_strands, unsigned n_shifts);
|
||||
|
||||
|
133
mpi_aux.cpp
Normal file
133
mpi_aux.cpp
Normal 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
20
mpi_aux.h
Normal 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
218
mpimain.cpp
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user