Merge branch 'master' of github.com:cseed/knotkit
Conflicts: knot_tables.cpp
This commit is contained in:
commit
b51dbfe2a0
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,8 +1,9 @@
|
||||
*~
|
||||
*.o
|
||||
/gss
|
||||
/kk
|
||||
/main
|
||||
/testsurfaces
|
||||
/serial.cmd*
|
||||
/serial.cmd.[eo]*
|
||||
/parallel.cmd.[eo]*
|
||||
/save
|
||||
*/save
|
||||
|
43
Makefile
43
Makefile
@ -1,24 +1,28 @@
|
||||
|
||||
BISON = /opt/local/bin/bison
|
||||
FLEX = /opt/local/bin/flex
|
||||
devel = 0
|
||||
|
||||
CXX = g++
|
||||
BISON = bison
|
||||
FLEX = flex
|
||||
|
||||
INCLUDES = -I/opt/local/include -I.
|
||||
# CXX = g++
|
||||
# CXX = OMPI_CXX=clang++ mpic++ -fno-color-diagnostics --stdlib=libc++ --std=c++11 -I/u/cseed/llvm-3.1/lib/c++/v1
|
||||
CXX = clang++ -fno-color-diagnostics --stdlib=libc++ --std=c++11
|
||||
|
||||
INCLUDES = -I. -I/opt/local/include
|
||||
|
||||
# OPTFLAGS = -g
|
||||
OPTFLAGS = -O2 -g
|
||||
# OPTFLAGS = -O2 -DNDEBUG
|
||||
|
||||
LDFLAGS = -L/opt/local/lib
|
||||
# LDFLAGS = -pg -L/opt/local/lib
|
||||
|
||||
CXXFLAGS = $(OPTFLAGS) -Wall -Wno-unused $(INCLUDES)
|
||||
CXXFLAGS = $(OPTFLAGS) -DHOME="\"`pwd`\"" -Wall -Wno-unused $(INCLUDES)
|
||||
|
||||
LIB_OBJS = lib/refcount.o \
|
||||
lib/lib.o lib/smallbitset.o lib/bitset.o lib/setcommon.o lib/io.o lib/directed_multigraph.o
|
||||
ALGEBRA_OBJS = algebra/algebra.o algebra/grading.o algebra/polynomial.o
|
||||
KNOTKIT_OBJS = planar_diagram.o dt_code.o knot_diagram.o cube.o spanning_tree_complex.o \
|
||||
KNOTKIT_OBJS = planar_diagram.o dt_code.o knot_diagram.o cube.o steenrod_square.o \
|
||||
spanning_tree_complex.o \
|
||||
smoothing.o cobordism.o knot_tables.o sseq.o \
|
||||
knot_parser/knot_parser.o knot_parser/knot_scanner.o \
|
||||
rd_parser/rd_parser.o rd_parser/rd_scanner.o
|
||||
@ -26,7 +30,8 @@ KNOTKIT_OBJS = planar_diagram.o dt_code.o knot_diagram.o cube.o spanning_tree_co
|
||||
COMMON_OBJS = $(KNOTKIT_OBJS) $(ALGEBRA_OBJS) $(LIB_OBJS)
|
||||
|
||||
LIB_HEADERS = lib/lib.h lib/show.h lib/refcount.h lib/pair.h lib/maybe.h lib/vector.h \
|
||||
lib/set.h lib/ullmanset.h lib/bitset.h lib/smallbitset.h lib/setcommon.h \
|
||||
lib/set_wrapper.h lib/set.h lib/hashset.h \
|
||||
lib/ullmanset.h lib/bitset.h lib/smallbitset.h lib/setcommon.h \
|
||||
lib/map_wrapper.h lib/map.h lib/hashmap.h lib/ullmanmap.h lib/mapcommon.h \
|
||||
lib/unionfind.h lib/priority_queue.h lib/io.h \
|
||||
lib/directed_multigraph.h
|
||||
@ -36,11 +41,12 @@ ALGEBRA_HEADERS = algebra/algebra.h algebra/grading.h algebra/module.h \
|
||||
algebra/polynomial.h algebra/multivariate_polynomial.h \
|
||||
algebra/multivariate_laurentpoly.h algebra/fraction_field.h
|
||||
KNOTKIT_HEADERS = knotkit.h planar_diagram.h dt_code.h knot_diagram.h \
|
||||
smoothing.h cobordism.h cube.h spanning_tree_complex.h cube_impl.h sseq.h
|
||||
smoothing.h cobordism.h cube.h steenrod_square.h \
|
||||
spanning_tree_complex.h cube_impl.h sseq.h simplify_chain_complex.h
|
||||
|
||||
LIBS = -lgmp
|
||||
LIBS = -lgmp -lz
|
||||
|
||||
all: gss
|
||||
all: kk
|
||||
|
||||
%.o : %.cc
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
@ -48,15 +54,19 @@ all: gss
|
||||
%.o : %.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
gss: gss.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o gss $^ $(LIBS)
|
||||
kk: kk.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o kk $^ $(LIBS)
|
||||
|
||||
main: main.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o main $^ $(LIBS)
|
||||
|
||||
mpimain: mpimain.o mpi_aux.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o mpimain $^ $(LIBS)
|
||||
|
||||
testlib: testlib.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o testlib $^
|
||||
|
||||
ifeq ($(devel),1)
|
||||
knot_parser/knot_parser.cc knot_parser/knot_parser.hh: knot_parser/knot_parser.yy
|
||||
$(BISON) knot_parser/knot_parser.yy -o knot_parser/knot_parser.cc
|
||||
|
||||
@ -74,6 +84,7 @@ rd_parser/rd_parser.cc rd_parser/rd_parser.hh: rd_parser/rd_parser.yy
|
||||
|
||||
rd_parser/rd_scanner.cc: rd_parser/rd_scanner.ll
|
||||
$(FLEX) -o rd_parser/rd_scanner.cc rd_parser/rd_scanner.ll
|
||||
endif
|
||||
|
||||
.PHONY: parser_files
|
||||
parser_files: \
|
||||
@ -87,7 +98,7 @@ parser_files: \
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o lib/*.o algebra/*.o knot_parser/*.o rd_parser/*.o
|
||||
rm -f main gss
|
||||
rm -f main kk mpimain
|
||||
rm -f gmon.out
|
||||
|
||||
.PHONY: realclean
|
||||
@ -104,4 +115,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 kk.o: $(KNOTKIT_HEADERS) $(ALGEBRA_HEADERS) $(LIB_HEADERS)
|
||||
|
||||
mpimain.o mpi_aux.o: mpi_aux.h
|
||||
|
163
README
163
README
@ -1 +1,162 @@
|
||||
I modified cotton's readme.
|
||||
knotkit is a C++ software package written by Cotton Seed
|
||||
(cseed@math.princeton.edu) for computing some knot and manifold
|
||||
invariants appearing in low-dimensional topology. Other contributors
|
||||
include Josh Batson.
|
||||
|
||||
TABLE OF CONTENTS
|
||||
|
||||
1. INTRO
|
||||
2. BUILDING
|
||||
3. USAGE
|
||||
4. UPCOMING CHANGES
|
||||
5. FOR DEVELOPERS
|
||||
|
||||
1. INTRO
|
||||
|
||||
In addition to accepting knot presentations in a variety of formats
|
||||
(see usage below), knotkit contains the following tables of knot data:
|
||||
|
||||
* The Rolfsen knot tables through 10 crossings, extracted from
|
||||
Bar-Natan's Mathematica package, KnotTheory`,
|
||||
* The Hoste-Weeks-Thistlewaite knot tables through 16 crossings taken
|
||||
from knotscape, and
|
||||
* and the Morwen Thistlewaite hyperbolic link tables taken from
|
||||
SnapPy.
|
||||
|
||||
This version of knotkit has support to compute the following
|
||||
invariants:
|
||||
|
||||
* Khovanov homology
|
||||
See:
|
||||
M. Khovanov, A Categorification of the Jones Polynomial, Duke
|
||||
Math. J. 101 (2000), 359--426, arXiv:math/9908171.
|
||||
D. Bar-Natan, On Khovanov's Categorification of the Jones Polynomial,
|
||||
Algebraic and Geometric Topology 2 (2002), 337--370.
|
||||
|
||||
* Szabo's geometric spectral sequence
|
||||
Computing gss was the original motivation for writing knotkit. For
|
||||
more information on gss, see:
|
||||
Z. Szabo, A geometric spectral sequence in Khovanov homology,
|
||||
arXiv:1010.4252, and
|
||||
C. Seed, Computations of Szabo's Geometric Spectral Sequence in Khovanov
|
||||
Homology, arXiv:1110.0735.
|
||||
|
||||
* The Batson-Seed link splitting spectral sequence
|
||||
See:
|
||||
J. Batson, C. Seed, A Link Splitting Spectral Sequence in Khovanov
|
||||
Homology.
|
||||
|
||||
* The Lipshitz-Sarkar Steenrod square on Khovanov homology
|
||||
See:
|
||||
R. Lipshitz, S. Sarkar, A Khovanov Homotopy Type, arXiv:1112.3932.
|
||||
R. Lipshitz, S. Sarkar, A Steenrod Square on Khovanov Homology,
|
||||
arXiv:1204.5776.
|
||||
|
||||
* Bar-Natan's analogue of Lee homology
|
||||
See:
|
||||
E. S. Lee, An endomorphism of the Khovanov invariant, Adv. Math. 197
|
||||
(2005), 2, 554–586, arXiv:math/0210213.
|
||||
D. Bar-Natan, Khovanov’s homology for tangles and cobordisms,
|
||||
Geom. Topol. 9 (2005), 1443–1499, arXiv:math/0410495.
|
||||
R. Lipshitz, S. Sarkar, A refinement of Rasmussen's s-invariant,
|
||||
arXiv:1206.3532.
|
||||
|
||||
* The s-invariant coming from Bar-Natan's analogue of Lee homology
|
||||
In addition to the above references, see:
|
||||
J. Rasmussen, Khovanov homology and the slice genus, Invent.
|
||||
Math. 182 2 (2010), 419--447, arXiv:math/0402131.
|
||||
R. Lipshitz, S. Sarkar, A refinement of Rasmussen's s-invariant,
|
||||
arXiv:1206.3532.
|
||||
|
||||
2. BUILDING
|
||||
|
||||
To build knotkit on OS X, you will need the latest version of XCode
|
||||
(available for free in the App Store) and the GNU multiple precision
|
||||
arithmetic library (GMP). You can get GMP here:
|
||||
|
||||
http://gmplib.org/
|
||||
|
||||
knotkit also builds under Linux. In addition to GMP, you will need a
|
||||
C++ compiler which supports C++11. I use LLVM clang, but knotkit
|
||||
should build with a recent version of GCC.
|
||||
|
||||
knotkit doesn't have a sophisticated build system. To build knotkit,
|
||||
just run:
|
||||
|
||||
make
|
||||
|
||||
from the knotkit source directory. This should build the executable
|
||||
"kk". For instructions on invoking kk, see usage below. If you run
|
||||
into a problem, please contact me: Cotton Seed
|
||||
(cotton@math.princeton.edu).
|
||||
|
||||
3. USAGE
|
||||
|
||||
The usage message for kk is given below. This can also be obtained by
|
||||
running "kk -h".
|
||||
|
||||
A note about output. The output for commands kh, gss, ls and lee is a
|
||||
.tex file which renders the bigraded homology group or spectral
|
||||
sequence. The output for the command sq2 matches the output for the
|
||||
program written by Lipshitz-Sarkar and is suitable for loading into
|
||||
Sage. The command s outputs a single line of text.
|
||||
|
||||
usage: kk <invariant> [options...] <link>
|
||||
compute <invariant> for knot or link <link>
|
||||
<invariant> can be one of:
|
||||
kh: Khovanov homology
|
||||
gss: Szabo's geometric spectral sequence
|
||||
lsss: Batson-Seed link splitting spectral sequence
|
||||
component weights are 0, 1, ..., m
|
||||
sq2: Lipshitz-Sarkar Steenrod square on Z/2 Kh
|
||||
output suitable for Sage
|
||||
leess: spectral sequence coming from Bar-Natan analogue of Lee's
|
||||
deformation of Khovanov's complex (whew!)
|
||||
s: Rasmussen's s-invariant coming from lee
|
||||
output:
|
||||
kh, gss, lsss, leess: .tex file
|
||||
sq2: text in Sage format
|
||||
s: text
|
||||
options:
|
||||
-r : compute reduced theory
|
||||
-h : print this message
|
||||
-o <file> : write output to <file>
|
||||
(stdout is the default)
|
||||
-f <field> : ground field (if applicable)
|
||||
(Z2 is the default)
|
||||
-v : verbose: report progress as the computation proceeds
|
||||
<field> can be one of:
|
||||
Z2, Z3, Q
|
||||
<link> can be one of:
|
||||
- the unknot, e.g. U or unknot
|
||||
- a torus knot, e.g. T(2,3)
|
||||
- a Rolfsen table knot, e.g. 10_124
|
||||
- a Hoste-Thistlethwaite-Weeks knot, e.g. 11a12 or 12n214
|
||||
- a Morwen Thistlethwaite link, e.g. L8n9 or L13n8862
|
||||
- a planar diagram, e.g.
|
||||
PD[X[1, 4, 2, 5], X[3, 6, 4, 1], X[5, 2, 6, 3]] or
|
||||
PD[[1, 4, 2, 5], [3, 6, 4, 1], [5, 2, 6, 3]]
|
||||
- a Dowker-Thistlethwaite code, e.g.
|
||||
DTCode[6,8,2,4],
|
||||
DT[dadbcda] or
|
||||
DT[{6, -8}, {-10, 12, -14, 2, -4}]
|
||||
- a braid, e.g. BR[2, {-1, -1, -1}]
|
||||
- disjoint union (juxtaposition), e.g. T(2,3) U
|
||||
|
||||
4. UPCOMING CHANGES
|
||||
|
||||
The following changes are currently planned:
|
||||
|
||||
* support for Z/p, p arbitrary prime and F(x) field of rational functions
|
||||
* Roberts' totally twisted Khovanov homology
|
||||
* the E^3 page of the twisted spectral sequence Kh(L) => \widehat{HF}(\Sigma_L)
|
||||
* spectral sequences of PIDs: lsss over F[x], gss over Z
|
||||
* maps induced by cobordisms
|
||||
|
||||
5. FOR DEVELOPERS
|
||||
|
||||
If you are interested in contributing to knotkit or using it for a new
|
||||
application, please contact me: Cotton Seed
|
||||
(cotton@math.princeton.edu). I am interested in developing knotkit to
|
||||
be an open platform for performing computations arising in
|
||||
low-dimensional topology.
|
||||
|
14
algebra/Q.h
14
algebra/Q.h
@ -31,16 +31,16 @@ class Q
|
||||
Q_impl (reader &r)
|
||||
{
|
||||
mpq_init (x);
|
||||
mpz_inp_raw (mpq_numref (x), r.fp);
|
||||
mpz_inp_raw (mpq_denref (x), r.fp);
|
||||
r.read_mpz (mpq_numref (x));
|
||||
r.read_mpz (mpq_denref (x));
|
||||
}
|
||||
|
||||
~Q_impl () { mpq_clear (x); }
|
||||
|
||||
void write_self (writer &w) const
|
||||
{
|
||||
mpz_out_raw (w.fp, mpq_numref (x));
|
||||
mpz_out_raw (w.fp, mpq_denref (x));
|
||||
w.write_mpz (mpq_numref (x));
|
||||
w.write_mpz (mpq_denref (x));
|
||||
}
|
||||
};
|
||||
|
||||
@ -163,12 +163,12 @@ class Q
|
||||
|
||||
Q div (const Q &d) const { return operator / (d); }
|
||||
|
||||
triple<Q, Q, Q> extended_gcd (const Q &q) const
|
||||
tuple<Q, Q, Q> extended_gcd (const Q &q) const
|
||||
{
|
||||
if (*this != 0)
|
||||
return triple<Q, Q, Q> (*this, 1, 0);
|
||||
return tuple<Q, Q, Q> (*this, 1, 0);
|
||||
else
|
||||
return triple<Q, Q, Q> (q, 0, 1);
|
||||
return tuple<Q, Q, Q> (q, 0, 1);
|
||||
}
|
||||
|
||||
Q gcd (const Q &q) const
|
||||
|
55
algebra/Z.h
55
algebra/Z.h
@ -21,14 +21,14 @@ class Z
|
||||
Z_impl (reader &r)
|
||||
{
|
||||
mpz_init (x);
|
||||
mpz_inp_raw (x, r.fp);
|
||||
r.read_mpz (x);
|
||||
}
|
||||
|
||||
~Z_impl () { mpz_clear (x); }
|
||||
|
||||
void write_self (writer &w) const
|
||||
{
|
||||
mpz_out_raw (w.fp, x);
|
||||
w.write_mpz (x);
|
||||
}
|
||||
};
|
||||
|
||||
@ -48,6 +48,7 @@ class Z
|
||||
Z &operator = (int x) { impl = new Z_impl (x); return *this; }
|
||||
|
||||
bool operator == (const Z &z) const { return mpz_cmp (impl->x, z.impl->x) == 0; }
|
||||
bool operator != (const Z &z) const { return !operator == (z); }
|
||||
|
||||
bool operator == (int y) const { return mpz_cmp_si (impl->x, y) == 0; }
|
||||
bool operator != (int y) const { return !operator == (y); }
|
||||
@ -91,13 +92,13 @@ class Z
|
||||
return Z (STEAL, x);
|
||||
}
|
||||
|
||||
Z operator / (const Z &z) const
|
||||
Z operator / (const Z &denom) const
|
||||
{
|
||||
if (mpz_cmp_si (z.impl->x, 1) == 0)
|
||||
if (mpz_cmp_si (denom.impl->x, 1) == 0)
|
||||
return *this;
|
||||
else
|
||||
{
|
||||
assert (mpz_cmp_si (z.impl->x, -1) == 0);
|
||||
assert (mpz_cmp_si (denom.impl->x, -1) == 0);
|
||||
|
||||
mpz_t x;
|
||||
mpz_init (x);
|
||||
@ -112,6 +113,7 @@ class Z
|
||||
return Z (COPY, *this);
|
||||
}
|
||||
|
||||
// *this += z1*z2
|
||||
Z &muladdeq (const Z &z1, const Z &z2)
|
||||
{
|
||||
mpz_addmul (impl->x, z1.impl->x, z2.impl->x);
|
||||
@ -148,33 +150,30 @@ class Z
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool divides (const Z &n) const
|
||||
bool divides (const Z &num) const
|
||||
{
|
||||
// d = *this
|
||||
return mpz_divisible_p (n.impl->x, impl->x);
|
||||
return mpz_divisible_p (num.impl->x, impl->x);
|
||||
}
|
||||
bool operator | (const Z &num) const { return divides (num); }
|
||||
|
||||
bool operator | (const Z &z) const { return divides (z); }
|
||||
|
||||
Z div (const Z &d) const
|
||||
Z divide_exact (const Z &denom) const
|
||||
{
|
||||
// n = *this
|
||||
// num = *this
|
||||
mpz_t q;
|
||||
mpz_init (q);
|
||||
mpz_divexact (q, impl->x, d.impl->x);
|
||||
mpz_divexact (q, impl->x, denom.impl->x);
|
||||
return Z (STEAL, q);
|
||||
}
|
||||
|
||||
triple<Z, Z, Z> extended_gcd (const Z &z) const
|
||||
tuple<Z, Z> divide_with_remainder (const Z &denom) const
|
||||
{
|
||||
mpz_t d, s, t;
|
||||
mpz_init (d);
|
||||
mpz_init (s);
|
||||
mpz_init (t);
|
||||
mpz_gcdext (d, s, t, impl->x, z.impl->x);
|
||||
return triple<Z, Z, Z> (Z (STEAL, d),
|
||||
Z (STEAL, s),
|
||||
Z (STEAL, t));
|
||||
// *this = num
|
||||
mpz_t q, r;
|
||||
mpz_init (q);
|
||||
mpz_init (r);
|
||||
mpz_tdiv_qr (q, r, impl->x, denom.impl->x);
|
||||
return make_tuple (Z (STEAL, q),
|
||||
Z (STEAL, r));
|
||||
}
|
||||
|
||||
Z gcd (const Z &z) const
|
||||
@ -191,6 +190,18 @@ class Z
|
||||
return Z (STEAL, m);
|
||||
}
|
||||
|
||||
tuple<Z, Z, Z> extended_gcd (const Z &z) const
|
||||
{
|
||||
mpz_t d, s, t;
|
||||
mpz_init (d);
|
||||
mpz_init (s);
|
||||
mpz_init (t);
|
||||
mpz_gcdext (d, s, t, impl->x, z.impl->x);
|
||||
return make_tuple (Z (STEAL, d),
|
||||
Z (STEAL, s),
|
||||
Z (STEAL, t));
|
||||
}
|
||||
|
||||
static void show_ring () { printf ("Z"); }
|
||||
void show_self () const { mpz_out_str (stdout, 10, impl->x); }
|
||||
void display_self () const { show_self (); newline (); }
|
||||
|
16
algebra/Z2.h
16
algebra/Z2.h
@ -11,15 +11,18 @@ class Z2
|
||||
public:
|
||||
Z2 () : v(0) { }
|
||||
Z2 (int x) : v((bool)(x & 1)) { }
|
||||
Z2 (unsigned x) : v((bool)(x & 1)) { }
|
||||
Z2 (bool v_) : v(v_) { }
|
||||
Z2 (const Z2 &x) : v(x.v) { }
|
||||
Z2 (copy, const Z2 &x) : v(x.v) { }
|
||||
Z2 (reader &r) { v = r.read_bool (); }
|
||||
~Z2 () { }
|
||||
|
||||
Z2 &operator = (const Z2 &x) { v = x.v; return *this; }
|
||||
Z2 &operator = (int x) { v = (bool)(x & 1); return *this; }
|
||||
|
||||
bool operator == (const Z2 &x) const { return v == x.v; }
|
||||
bool operator != (const Z2 &x) const { return v != x.v; }
|
||||
|
||||
bool operator == (int x) const { return v == (bool)(x & 1); }
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
@ -39,6 +42,12 @@ class Z2
|
||||
Z2 &operator *= (const Z2 &x) { v &= x.v; return *this; }
|
||||
Z2 &operator /= (const Z2 &x) { assert (x.v); return *this; }
|
||||
|
||||
// *this += z1*z2
|
||||
Z2 &muladdeq (const Z2 &z1, const Z2 &z2)
|
||||
{
|
||||
return operator += (z1 * z2);
|
||||
}
|
||||
|
||||
bool divides (Z2 x) const { return v || !x.v; }
|
||||
bool operator | (const Z2 x) const { return divides (x); }
|
||||
|
||||
@ -54,15 +63,16 @@ class Z2
|
||||
return Z2 (1);
|
||||
}
|
||||
|
||||
triple<Z2, Z2, Z2> extended_gcd (Z2 x) const
|
||||
tuple<Z2, Z2, Z2> extended_gcd (Z2 x) const
|
||||
{
|
||||
if (v)
|
||||
return triple<Z2, Z2, Z2> (Z2 (1), Z2 (1), Z2 (0));
|
||||
return make_tuple (Z2 (1), Z2 (1), Z2 (0));
|
||||
else
|
||||
return triple<Z2, Z2, Z2> (Z2 (1), Z2 (0), Z2 (1));
|
||||
return make_tuple (Z2 (1), Z2 (0), Z2 (1));
|
||||
}
|
||||
|
||||
static void show_ring () { printf ("Z2"); }
|
||||
void write_self (writer &w) const { w.write_bool (v); }
|
||||
void show_self () const { printf ("%d", (int)v); }
|
||||
void display_self () const { printf ("%d\n", (int)v); }
|
||||
};
|
||||
|
15
algebra/Zp.h
15
algebra/Zp.h
@ -32,6 +32,7 @@ class Zp
|
||||
}
|
||||
|
||||
bool operator == (const Zp &x) const { return v == x.v; }
|
||||
bool operator != (const Zp &x) const { return !operator == (x); }
|
||||
|
||||
bool operator == (int x) const { return operator == (Zp (x)); }
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
@ -56,11 +57,11 @@ class Zp
|
||||
|
||||
Zp recip () const
|
||||
{
|
||||
triple<unsigned, int, int> t = unsigned_extended_gcd (v, p);
|
||||
assert (t.first == 1);
|
||||
assert ((int)t.first == t.second*(int)v + t.third*(int)p);
|
||||
tuple<unsigned, int, int> t = unsigned_extended_gcd (v, p);
|
||||
assert (get<0> (t) == 1);
|
||||
assert ((int)get<0> (t) == get<1> (t)*(int)v + get<2> (t)*(int)p);
|
||||
|
||||
return Zp (t.second);
|
||||
return Zp (get<1> (t));
|
||||
}
|
||||
|
||||
Zp &operator += (const Zp &x)
|
||||
@ -92,12 +93,12 @@ class Zp
|
||||
|
||||
Zp div (const Zp &d) const { return operator / (d); }
|
||||
|
||||
triple<Zp, Zp, Zp> extended_gcd (const Zp &x) const
|
||||
tuple<Zp, Zp, Zp> extended_gcd (const Zp &x) const
|
||||
{
|
||||
if (v)
|
||||
return triple<Zp, Zp, Zp> (v, 1, 0);
|
||||
return make_tuple (v, Zp (1), Zp (0));
|
||||
else
|
||||
return triple<Zp, Zp, Zp> (x, 0, 1);
|
||||
return make_tuple (x, Zp (0), Zp (1));
|
||||
}
|
||||
|
||||
Zp gcd (const Zp &x) const
|
||||
|
@ -16,8 +16,8 @@ unsigned_gcd (unsigned a, unsigned b)
|
||||
unsigned
|
||||
int_gcd (int a, int b)
|
||||
{
|
||||
return unsigned_gcd ((unsigned)std::abs (a),
|
||||
(unsigned)std::abs (b));
|
||||
return unsigned_gcd ((unsigned)abs (a),
|
||||
(unsigned)abs (b));
|
||||
}
|
||||
|
||||
uint64
|
||||
@ -35,47 +35,47 @@ uint64_gcd (uint64 a, uint64 b)
|
||||
uint64
|
||||
int64_gcd (int64 a, int64 b)
|
||||
{
|
||||
return uint64_gcd ((uint64)std::abs (a),
|
||||
(uint64)std::abs (b));
|
||||
return uint64_gcd ((uint64)abs64 (a),
|
||||
(uint64)abs64 (b));
|
||||
}
|
||||
|
||||
static triple<unsigned, int, int>
|
||||
static tuple<unsigned, int, int>
|
||||
extended_gcd_1 (int a, int b)
|
||||
{
|
||||
if (b == 0)
|
||||
return triple<unsigned, int, int> (a, 1, 0);
|
||||
return tuple<unsigned, int, int> (a, 1, 0);
|
||||
|
||||
unsigned t = a % b;
|
||||
if (!t)
|
||||
return triple<unsigned, int, int> (b, 0, 1);
|
||||
return make_tuple (b, 0, 1);
|
||||
else
|
||||
{
|
||||
triple<unsigned, int, int> s = unsigned_extended_gcd (b, t);
|
||||
tuple<unsigned, int, int> s = unsigned_extended_gcd (b, t);
|
||||
|
||||
unsigned d = s.first;
|
||||
int x = s.third,
|
||||
y = s.second - s.third * (a / b);
|
||||
unsigned d = get<0> (s);
|
||||
int x = get<2> (s),
|
||||
y = get<1> (s) - get<2> (s) * (a / b);
|
||||
|
||||
assert ((int)d == a*x + b*y);
|
||||
|
||||
return triple<unsigned, int, int> (d, x, y);
|
||||
return make_tuple (d, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
triple<unsigned, int, int>
|
||||
tuple<unsigned, int, int>
|
||||
unsigned_extended_gcd (unsigned a, unsigned b)
|
||||
{
|
||||
return extended_gcd_1 ((int)a, (int)b);
|
||||
}
|
||||
|
||||
triple<unsigned, int, int>
|
||||
tuple<unsigned, int, int>
|
||||
extended_gcd (int a, int b)
|
||||
{
|
||||
triple<unsigned, int, int> t = extended_gcd_1 (std::abs (a),
|
||||
std::abs (b));
|
||||
unsigned d = t.first;
|
||||
int x = t.second,
|
||||
y = t.third;
|
||||
tuple<unsigned, int, int> t = extended_gcd_1 (abs (a),
|
||||
abs (b));
|
||||
unsigned d = get<0> (t);
|
||||
int x = get<1> (t),
|
||||
y = get<2> (t);
|
||||
if (a < 0)
|
||||
x *= -1;
|
||||
if (b < 0)
|
||||
@ -83,7 +83,7 @@ extended_gcd (int a, int b)
|
||||
|
||||
assert ((int)d == a*x + b*y);
|
||||
|
||||
return triple<unsigned, int, int> (d, x, y);
|
||||
return make_tuple (d, x, y);
|
||||
}
|
||||
|
||||
unsigned
|
||||
@ -100,12 +100,12 @@ uint64_lcm (uint64 a, uint64 b)
|
||||
|
||||
unsigned int_lcm (int a, int b)
|
||||
{
|
||||
return unsigned_lcm ((unsigned)std::abs (a),
|
||||
(unsigned)std::abs (b));
|
||||
return unsigned_lcm ((unsigned)abs (a),
|
||||
(unsigned)abs (b));
|
||||
}
|
||||
|
||||
uint64 int64_lcm (int64 a, int64 b)
|
||||
{
|
||||
return uint64_lcm ((uint64)std::abs (a),
|
||||
(uint64)std::abs (b));
|
||||
return uint64_lcm ((uint64)abs64 (a),
|
||||
(uint64)abs64 (b));
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
#include <gmp.h>
|
||||
|
||||
#include <lib/lib.h>
|
||||
|
||||
inline int recip (int x)
|
||||
@ -42,9 +40,9 @@ unsigned int_lcm (int a, int b);
|
||||
uint64 int64_lcm (int64 a, int64 b);
|
||||
|
||||
// (d, x, y) = gcd (a, b) where x*a + y*b = d
|
||||
triple<unsigned, int, int> extended_gcd (int a, int b);
|
||||
tuple<unsigned, int, int> extended_gcd (int a, int b);
|
||||
|
||||
triple<unsigned, int, int> unsigned_extended_gcd (unsigned a, unsigned b);
|
||||
tuple<unsigned, int, int> unsigned_extended_gcd (unsigned a, unsigned b);
|
||||
|
||||
template<class R> class linear_combination;
|
||||
template<class R> class linear_combination_const_iter;
|
||||
|
@ -36,6 +36,7 @@ template<class T> class fraction_field
|
||||
fraction_field &operator = (int x) { num = x; denom = 1; return *this; }
|
||||
|
||||
bool operator == (const fraction_field &q) const { return num * q.denom == q.num * denom; }
|
||||
bool operator != (const fraction_field &q) const { return !operator == (q); }
|
||||
|
||||
bool operator == (int x) const { return num == denom * T (x); }
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
@ -66,6 +67,11 @@ template<class T> class fraction_field
|
||||
return fraction_field (new_num, denom*xe);
|
||||
}
|
||||
|
||||
fraction_field operator - () const
|
||||
{
|
||||
return fraction_field (-num, denom);
|
||||
}
|
||||
|
||||
fraction_field operator * (const fraction_field &x) const
|
||||
{
|
||||
T d1 = num.gcd (x.denom);
|
||||
@ -187,12 +193,12 @@ template<class T> class fraction_field
|
||||
return fraction_field (1);
|
||||
}
|
||||
|
||||
triple<fraction_field, fraction_field, fraction_field> extended_gcd (const fraction_field &x) const
|
||||
tuple<fraction_field, fraction_field, fraction_field> extended_gcd (const fraction_field &x) const
|
||||
{
|
||||
if (*this != 0)
|
||||
return triple<fraction_field, fraction_field, fraction_field> (*this, 1, 0);
|
||||
return make_tuple (*this, fraction_field (1), fraction_field (0));
|
||||
else
|
||||
return triple<fraction_field, fraction_field, fraction_field> (x, 0, 1);
|
||||
return make_tuple (x, fraction_field (0), fraction_field (1));
|
||||
}
|
||||
|
||||
static void show_ring () { printf ("fraction_field("); T::show_ring (); printf (")"); }
|
||||
@ -210,7 +216,6 @@ fraction_field<T>::reduce ()
|
||||
}
|
||||
|
||||
T d = num.gcd (denom);
|
||||
|
||||
num = num.divide_exact (d);
|
||||
denom = denom.divide_exact (d);
|
||||
}
|
||||
@ -220,7 +225,6 @@ fraction_field<T>::check ()
|
||||
{
|
||||
if (num == 0)
|
||||
return;
|
||||
// check denom == 1
|
||||
|
||||
// assert (num.gcd (denom) == 1);
|
||||
}
|
||||
|
@ -8,6 +8,12 @@ class grading
|
||||
grading () : h(0), q(0) { }
|
||||
grading (int h_, int q_) : h(h_), q(q_) { }
|
||||
grading (const grading &gr) : h(gr.h), q(gr.q) { }
|
||||
grading (reader &r)
|
||||
{
|
||||
h = r.read_int ();
|
||||
q = r.read_int ();
|
||||
}
|
||||
|
||||
~grading () { }
|
||||
|
||||
grading &operator = (const grading &gr) { h = gr.h; q = gr.q; return *this; }
|
||||
@ -36,6 +42,8 @@ class grading
|
||||
}
|
||||
|
||||
bool operator == (const grading &gr) const { return h == gr.h && q == gr.q; }
|
||||
bool operator != (const grading &gr) const { return !operator == (gr); }
|
||||
|
||||
bool operator < (const grading &gr) const
|
||||
{
|
||||
return h < gr.h
|
||||
@ -43,7 +51,13 @@ class grading
|
||||
}
|
||||
|
||||
grading mirror_grading (unsigned nplus, unsigned nminus, bool torsion) const;
|
||||
|
||||
|
||||
void write_self (writer &w) const
|
||||
{
|
||||
w.write_int (h);
|
||||
w.write_int (q);
|
||||
}
|
||||
|
||||
void show_self () const;
|
||||
void display_self () const;
|
||||
};
|
||||
|
@ -39,8 +39,15 @@ class linear_combination
|
||||
for (typename map<unsigned, R>::const_iter i = lc.v; i; i ++)
|
||||
v.push (i.key (), R (COPY, i.val ()));
|
||||
}
|
||||
|
||||
linear_combination (reader &r)
|
||||
{
|
||||
m = r.read_mod<R> ();
|
||||
v = map<unsigned, R> (r);
|
||||
}
|
||||
|
||||
~linear_combination () { }
|
||||
|
||||
|
||||
linear_combination &operator = (const linear_combination &lc)
|
||||
{
|
||||
m = lc.m;
|
||||
@ -55,6 +62,7 @@ class linear_combination
|
||||
lc3 -= lc2;
|
||||
return lc3 == 0;
|
||||
}
|
||||
bool operator != (const linear_combination &lc) const { return !operator == (lc); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
@ -163,6 +171,12 @@ class linear_combination
|
||||
assert (!m->is_zero (i.val (), i.key ()));
|
||||
}
|
||||
#endif
|
||||
|
||||
void write_self (writer &w) const
|
||||
{
|
||||
write (w, *m);
|
||||
write (w, v);
|
||||
}
|
||||
|
||||
void show_self () const;
|
||||
void display_self () const { show_self (); newline (); }
|
||||
@ -336,6 +350,12 @@ class linear_combination<Z2>
|
||||
linear_combination (ptr<const Z2mod> m_) : m(m_) { }
|
||||
linear_combination (const linear_combination &lc) : m(lc.m), v(lc.v) { }
|
||||
linear_combination (copy, const linear_combination &lc) : m(lc.m), v(COPY, lc.v) { }
|
||||
linear_combination (reader &r)
|
||||
{
|
||||
m = r.read_mod<Z2> ();
|
||||
v = set<unsigned> (r);
|
||||
}
|
||||
|
||||
~linear_combination () { }
|
||||
|
||||
linear_combination &operator = (const linear_combination &lc)
|
||||
@ -346,6 +366,7 @@ class linear_combination<Z2>
|
||||
}
|
||||
|
||||
bool operator == (const linear_combination &lc) const { assert (m == lc.m); return v == lc.v; }
|
||||
bool operator != (const linear_combination &lc) const { return !operator == (lc); }
|
||||
|
||||
bool operator == (int x) const { assert (x == 0); return v.is_empty (); }
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
@ -445,6 +466,12 @@ class linear_combination<Z2>
|
||||
void check () const;
|
||||
#endif
|
||||
|
||||
void write_self (writer &w) const
|
||||
{
|
||||
write (w, *m);
|
||||
write (w, v);
|
||||
}
|
||||
|
||||
void show_self () const;
|
||||
void display_self () const { show_self (); newline (); }
|
||||
};
|
||||
|
419
algebra/module.h
419
algebra/module.h
@ -14,10 +14,15 @@ template<class R>
|
||||
class module : public refcounted
|
||||
{
|
||||
private:
|
||||
friend class reader;
|
||||
friend class writer;
|
||||
|
||||
unsigned id;
|
||||
|
||||
static unsigned id_counter;
|
||||
|
||||
static map<unsigned, ptr<const module<R> > > reader_id_module;
|
||||
|
||||
static map<basedvector<unsigned, 1>,
|
||||
ptr<const direct_sum<R> > > direct_sum_idx;
|
||||
static map<basedvector<unsigned, 1>,
|
||||
@ -28,13 +33,13 @@ class module : public refcounted
|
||||
public:
|
||||
module ()
|
||||
{
|
||||
id = id_counter;
|
||||
id_counter ++;
|
||||
id = id_counter;
|
||||
}
|
||||
module (const module &); // doesn't exist
|
||||
module (const module &) = delete;
|
||||
virtual ~module () { }
|
||||
|
||||
module &operator = (const module &); // doesn't exist
|
||||
module &operator = (const module &) = delete;
|
||||
|
||||
public:
|
||||
// the number of generators; n
|
||||
@ -48,6 +53,9 @@ class module : public refcounted
|
||||
|
||||
// r < i <= n
|
||||
virtual R generator_ann (unsigned i) const = 0;
|
||||
|
||||
basedvector<grading, 1> grading_vector () const;
|
||||
set<grading> gradings () const;
|
||||
|
||||
bool is_free () const { return dim () == free_rank (); }
|
||||
|
||||
@ -56,7 +64,12 @@ class module : public refcounted
|
||||
if (i <= free_rank ())
|
||||
return c == 0;
|
||||
else
|
||||
return generator_ann (i) | c;
|
||||
{
|
||||
// ???
|
||||
abort ();
|
||||
|
||||
// return generator_ann (i) | c;
|
||||
}
|
||||
}
|
||||
|
||||
R annihilator (R c, unsigned i) const
|
||||
@ -75,6 +88,7 @@ class module : public refcounted
|
||||
|
||||
multivariate_laurentpoly<Z> free_poincare_polynomial () const;
|
||||
multivariate_laurentpoly<Z> free_delta_poincare_polynomial () const;
|
||||
multivariate_laurentpoly<Z> free_ell_poincare_polynomial () const;
|
||||
|
||||
ptr<const direct_sum<R> >
|
||||
add (basedvector<ptr<const module<R> >, 1> compound_summands) const;
|
||||
@ -143,11 +157,16 @@ class module : public refcounted
|
||||
factors.append (this);
|
||||
}
|
||||
|
||||
ptr<const free_submodule<R> > graded_piece (grading hq) const;
|
||||
|
||||
void write_self (writer &w) const { w.write_mod<R> (this); }
|
||||
void show_self () const;
|
||||
void display_self () const;
|
||||
};
|
||||
|
||||
template<class R> unsigned module<R>::id_counter = 1;
|
||||
template<class R> unsigned module<R>::id_counter = 0;
|
||||
|
||||
template<class R> map<unsigned, ptr<const module<R> > > module<R>::reader_id_module;
|
||||
|
||||
template<class R> map<basedvector<unsigned, 1>,
|
||||
ptr<const direct_sum<R> > > module<R>::direct_sum_idx;
|
||||
@ -466,11 +485,11 @@ class base_module : public module<R>
|
||||
G g;
|
||||
|
||||
public:
|
||||
base_module (); // doesn't exist
|
||||
base_module () = delete;
|
||||
base_module (const G &g_) : g(g_) { }
|
||||
~base_module () { }
|
||||
|
||||
base_module &operator = (const base_module &); // doesn't exist
|
||||
base_module &operator = (const base_module &) = delete;
|
||||
|
||||
unsigned dim () const { return g.dim (); }
|
||||
unsigned free_rank () const { return g.free_rank (); }
|
||||
@ -487,17 +506,19 @@ class explicit_module : public module<R>
|
||||
basedvector<grading, 1> hq;
|
||||
|
||||
public:
|
||||
explicit_module (); // doesn't exist
|
||||
explicit_module () = delete;
|
||||
explicit_module (unsigned r_,
|
||||
basedvector<R, 1> ann_,
|
||||
basedvector<grading, 1> hq_)
|
||||
: r(r_), ann(ann_), hq(hq_)
|
||||
{ }
|
||||
{
|
||||
assert (hq.size () == r + ann.size ());
|
||||
}
|
||||
|
||||
explicit explicit_module (unsigned r_, basedvector<grading, 1> hq_) : r(r_), hq(hq_) { }
|
||||
~explicit_module () { }
|
||||
|
||||
explicit_module &operator = (const explicit_module &); // doesn't exist
|
||||
explicit_module &operator = (const explicit_module &) = delete;
|
||||
|
||||
unsigned dim () const { return r + ann.size (); }
|
||||
unsigned free_rank () const { return r; }
|
||||
@ -525,7 +546,7 @@ class free_submodule : public module<R>
|
||||
{ }
|
||||
~free_submodule () { }
|
||||
|
||||
free_submodule &operator = (const free_submodule &); // doesn't exist
|
||||
free_submodule &operator = (const free_submodule &) = delete;
|
||||
|
||||
ptr<const module<R> > parent_module () const { return parent; }
|
||||
|
||||
@ -542,6 +563,9 @@ class free_submodule : public module<R>
|
||||
|
||||
linear_combination<R> restrict (linear_combination<R> v0) const;
|
||||
ptr<const free_submodule<R> > restrict_submodule (ptr<const free_submodule<R> > m) const;
|
||||
|
||||
ptr<const free_submodule<R> > intersection (ptr<const free_submodule<R> > m) const;
|
||||
ptr<const free_submodule<R> > plus (ptr<const free_submodule<R> > m) const;
|
||||
};
|
||||
|
||||
template<class R>
|
||||
@ -562,13 +586,13 @@ class quotient_module : public module<R>
|
||||
basedvector<map<unsigned, R>, 1> pi;
|
||||
|
||||
public:
|
||||
quotient_module (const quotient_module &); // doesn't exist
|
||||
quotient_module (const quotient_module &) = delete;
|
||||
quotient_module (ptr<const module<R> > parent_)
|
||||
: parent(parent_)
|
||||
{ }
|
||||
~quotient_module () { }
|
||||
|
||||
quotient_module &operator = (const quotient_module &); // doesn't exsit
|
||||
quotient_module &operator = (const quotient_module &) = delete;
|
||||
|
||||
ptr<const module<R> > parent_module () const { return parent; }
|
||||
|
||||
@ -617,7 +641,7 @@ class map_impl : public refcounted
|
||||
ptr<const module<R> > to;
|
||||
|
||||
public:
|
||||
map_impl (const map_impl &); // doesn't exist
|
||||
map_impl (const map_impl &) = delete;
|
||||
map_impl (ptr<const module<R> > fromto)
|
||||
: from(fromto), to(fromto)
|
||||
{ }
|
||||
@ -626,9 +650,10 @@ class map_impl : public refcounted
|
||||
{ }
|
||||
virtual ~map_impl () { }
|
||||
|
||||
map_impl &operator = (const map_impl &); // doesn't exist
|
||||
map_impl &operator = (const map_impl &) = delete;
|
||||
|
||||
virtual linear_combination<R> column (unsigned i) const = 0;
|
||||
virtual const linear_combination<R> column (unsigned i) const = 0;
|
||||
virtual const linear_combination<R> column_copy (unsigned i) const { return column (i); }
|
||||
|
||||
linear_combination<R> map (const linear_combination<R> &lc) const
|
||||
{
|
||||
@ -657,7 +682,11 @@ class explicit_map_impl : public map_impl<R>
|
||||
{ }
|
||||
~explicit_map_impl () { }
|
||||
|
||||
linear_combination<R> column (unsigned i) const { return columns[i]; }
|
||||
const linear_combination<R> column (unsigned i) const { return columns[i]; }
|
||||
const linear_combination<R> column_copy (unsigned i) const
|
||||
{
|
||||
return linear_combination<R> (COPY, columns[i]);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
@ -667,7 +696,7 @@ class zero_map_impl : public map_impl<R>
|
||||
zero_map_impl (ptr<const module<R> > fromto) : map_impl<R>(fromto) { }
|
||||
zero_map_impl (ptr<const module<R> > from, ptr<const module<R> > to) : map_impl<R>(from, to) { }
|
||||
|
||||
linear_combination<R> column (unsigned i) const { return linear_combination<R> (this->to); }
|
||||
const linear_combination<R> column (unsigned i) const { return linear_combination<R> (this->to); }
|
||||
};
|
||||
|
||||
template<class R>
|
||||
@ -677,7 +706,7 @@ class id_map_impl : public map_impl<R>
|
||||
id_map_impl (ptr<const module<R> > fromto) : map_impl<R>(fromto) { }
|
||||
id_map_impl (ptr<const module<R> > from, ptr<const module<R> > to) : map_impl<R>(from, to) { }
|
||||
|
||||
linear_combination<R> column (unsigned i) const
|
||||
const linear_combination<R> column (unsigned i) const
|
||||
{
|
||||
linear_combination<R> r (this->to);
|
||||
r.muladd (1, i);
|
||||
@ -700,7 +729,7 @@ class composition_impl : public map_impl<R>
|
||||
assert (g->to == f->from);
|
||||
}
|
||||
|
||||
linear_combination<R> column (unsigned i) const
|
||||
const linear_combination<R> column (unsigned i) const
|
||||
{
|
||||
return f->map (g->column (i));
|
||||
}
|
||||
@ -721,7 +750,7 @@ class direct_sum_impl : public map_impl<R>
|
||||
{
|
||||
}
|
||||
|
||||
linear_combination<R> column (unsigned i) const
|
||||
const linear_combination<R> column (unsigned i) const
|
||||
{
|
||||
pair<unsigned, unsigned> p = f->from->project (g->from, i);
|
||||
|
||||
@ -756,7 +785,7 @@ class tensor_impl : public map_impl<R>
|
||||
{
|
||||
}
|
||||
|
||||
linear_combination<R> column (unsigned i) const
|
||||
const linear_combination<R> column (unsigned i) const
|
||||
{
|
||||
pair<unsigned, unsigned> p = f->from->generator_factors (g->from, i);
|
||||
|
||||
@ -849,6 +878,15 @@ class mod_map
|
||||
mod_map (const map_builder<R> &b)
|
||||
: impl(new explicit_map_impl<R> (b.from, b.to, b.columns))
|
||||
{ }
|
||||
|
||||
mod_map (reader &r)
|
||||
{
|
||||
ptr<const module<R> > from = r.read_mod<R> ();
|
||||
ptr<const module<R> > to = r.read_mod<R> ();
|
||||
basedvector<linear_combination<R>, 1> columns (r);
|
||||
impl = new explicit_map_impl<R> (from, to, columns);
|
||||
}
|
||||
|
||||
~mod_map () { }
|
||||
|
||||
mod_map &operator = (const mod_map &m) { impl = m.impl; return *this; }
|
||||
@ -867,6 +905,7 @@ class mod_map
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bool operator != (const mod_map &m) const { return !operator == (m); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
@ -883,8 +922,10 @@ class mod_map
|
||||
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
|
||||
linear_combination<R> column (unsigned i) const { return impl->column (i); }
|
||||
linear_combination<R> operator [] (unsigned i) const { return impl->column (i); }
|
||||
const linear_combination<R> column (unsigned i) const { return impl->column (i); }
|
||||
const linear_combination<R> operator [] (unsigned i) const { return impl->column (i); }
|
||||
|
||||
const linear_combination<R> column_copy (unsigned i) const { return impl->column_copy (i); }
|
||||
|
||||
linear_combination<R> map (const linear_combination<R> &lc) const { return impl->map (lc); }
|
||||
mod_map compose (const mod_map &m) const
|
||||
@ -908,6 +949,7 @@ class mod_map
|
||||
|
||||
// ?? add and other map operations should not be explicit
|
||||
mod_map operator + (const mod_map &m) const;
|
||||
mod_map operator * (const R &c) const;
|
||||
|
||||
bool homogeneous () const;
|
||||
void check_grading (grading delta) const;
|
||||
@ -917,6 +959,7 @@ class mod_map
|
||||
|
||||
// inj : im -> to
|
||||
ptr<const free_submodule<R> > image () const;
|
||||
ptr<const free_submodule<R> > image (basedvector<linear_combination<R>, 1> vs) const;
|
||||
|
||||
ptr<const quotient_module<R> > cokernel () const;
|
||||
|
||||
@ -934,9 +977,19 @@ class mod_map
|
||||
mod_map induced_map_to (ptr<const quotient_module<R> > new_to);
|
||||
mod_map induced_map (ptr<const quotient_module<R> > new_fromto);
|
||||
|
||||
mod_map graded_piece (grading hq) const;
|
||||
|
||||
// ???
|
||||
basedvector<linear_combination<R>, 1> explicit_columns () const;
|
||||
|
||||
void write_self (writer &w) const
|
||||
{
|
||||
// write explicitly
|
||||
write (w, *impl->from);
|
||||
write (w, *impl->to);
|
||||
write (w, explicit_columns ());
|
||||
}
|
||||
|
||||
void show_self () const;
|
||||
void display_self () const;
|
||||
};
|
||||
@ -1095,16 +1148,16 @@ quotient_helper<R>::improve_pivot_row (unsigned i, unsigned j, unsigned i2)
|
||||
}
|
||||
#endif
|
||||
|
||||
triple<R, R, R> t = rc.extended_gcd (r2c);
|
||||
assert (t.first == rc*t.second + t.third*r2c);
|
||||
tuple<R, R, R> t = rc.extended_gcd (r2c);
|
||||
assert (get<0> (t) == rc*get<1> (t) + get<2> (t)*r2c);
|
||||
|
||||
rows[i] = r*t.second + r2*t.third;
|
||||
rows[i2] = (rc.div (t.first))*r2 - (r2c.div (t.first))*r;
|
||||
rows[i] = r*get<1> (t) + r2*get<2> (t);
|
||||
rows[i2] = (rc.div (get<0> (t)))*r2 - (r2c.div (get<0> (t)))*r;
|
||||
|
||||
assert ((rc | r2c) == rc.divides (t.first));
|
||||
assert (!rc.divides (t.first) || rows[i2](j) == 0);
|
||||
assert ((rc | r2c) == rc.divides (get<0> (t)));
|
||||
assert (!rc.divides (get<0> (t)) || rows[i2](j) == 0);
|
||||
|
||||
return !rc.divides (t.first);
|
||||
return !rc.divides (get<0> (t));
|
||||
}
|
||||
|
||||
template<class R> bool
|
||||
@ -1149,8 +1202,8 @@ quotient_helper<R>::improve_pivot_column (unsigned i, unsigned j, unsigned j2)
|
||||
}
|
||||
#endif
|
||||
|
||||
triple<R, R, R> t = rc.extended_gcd (rc2);
|
||||
assert (t.first == rc*t.second + t.third*rc2);
|
||||
tuple<R, R, R> t = rc.extended_gcd (rc2);
|
||||
assert (get<0> (t) == rc*get<1> (t) + get<2> (t)*rc2);
|
||||
|
||||
for (unsigned k = 1; k <= rows.size (); k ++)
|
||||
{
|
||||
@ -1158,9 +1211,9 @@ quotient_helper<R>::improve_pivot_column (unsigned i, unsigned j, unsigned j2)
|
||||
R rkc = rk(j),
|
||||
rkc2 = rk(j2);
|
||||
|
||||
rk.set_coeff (rkc*t.second + rkc2*t.third,
|
||||
rk.set_coeff (rkc*get<1> (t) + rkc2*get<2> (t),
|
||||
j);
|
||||
rk.set_coeff (rkc2*(rc.div (t.first)) - rkc*(rc2.div (t.first)),
|
||||
rk.set_coeff (rkc2*(rc.div (get<0> (t))) - rkc*(rc2.div (get<0> (t))),
|
||||
j2);
|
||||
}
|
||||
|
||||
@ -1169,8 +1222,8 @@ quotient_helper<R>::improve_pivot_column (unsigned i, unsigned j, unsigned j2)
|
||||
|
||||
assert (g.hq () == g2.hq ());
|
||||
|
||||
generators[j] = (rc.div (t.first)) * g + (rc2.div (t.first)) * g2;
|
||||
generators[j2] = t.second * g2 - t.third * g;
|
||||
generators[j] = (rc.div (get<0> (t))) * g + (rc2.div (get<0> (t))) * g2;
|
||||
generators[j2] = get<1> (t) * g2 - get<2> (t) * g;
|
||||
|
||||
#if 0
|
||||
for (unsigned k = 1; k <= rows.size (); k ++)
|
||||
@ -1189,8 +1242,8 @@ quotient_helper<R>::improve_pivot_column (unsigned i, unsigned j, unsigned j2)
|
||||
R d = ginv(j),
|
||||
d2 = ginv(j2);
|
||||
|
||||
ginv.set_coeff (t.second*d + t.third*d2, j);
|
||||
ginv.set_coeff (rc.div (t.first) * d2 - rc2.div (t.first) * d, j2);
|
||||
ginv.set_coeff (get<1> (t)*d + get<2> (t)*d2, j);
|
||||
ginv.set_coeff (rc.div (get<0> (t)) * d2 - rc2.div (get<0> (t)) * d, j2);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -1207,10 +1260,10 @@ quotient_helper<R>::improve_pivot_column (unsigned i, unsigned j, unsigned j2)
|
||||
}
|
||||
#endif
|
||||
|
||||
assert ((rc | rc2) == rc.divides (t.first));
|
||||
assert (!rc.divides (t.first) || r(j2) == 0);
|
||||
assert ((rc | rc2) == rc.divides (get<0> (t)));
|
||||
assert (!rc.divides (get<0> (t)) || r(j2) == 0);
|
||||
|
||||
return !rc.divides (t.first);
|
||||
return !rc.divides (get<0> (t));
|
||||
}
|
||||
|
||||
template<class R> void
|
||||
@ -1437,6 +1490,58 @@ module<R>::free_delta_poincare_polynomial () const
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class R> multivariate_laurentpoly<Z>
|
||||
module<R>::free_ell_poincare_polynomial () const
|
||||
{
|
||||
multivariate_laurentpoly<Z> r;
|
||||
for (unsigned i = 1; i <= free_rank (); i ++)
|
||||
{
|
||||
grading hq = generator_grading (i);
|
||||
multivariate_laurent_monomial m;
|
||||
m.push_exponent (1, hq.h - hq.q);
|
||||
r.muladdeq (1, m);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class R> basedvector<grading, 1>
|
||||
module<R>::grading_vector () const
|
||||
{
|
||||
basedvector<grading, 1> v (dim ());
|
||||
for (unsigned i = 1; i <= dim (); i ++)
|
||||
v[i] = generator_grading (i);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<class R> set<grading>
|
||||
module<R>::gradings () const
|
||||
{
|
||||
set<grading> gs;
|
||||
for (unsigned i = 1; i <= dim (); i ++)
|
||||
gs += generator_grading (i);
|
||||
return gs;
|
||||
}
|
||||
|
||||
template<class R> ptr<const free_submodule<R> >
|
||||
module<R>::graded_piece (grading hq) const
|
||||
{
|
||||
basedvector<linear_combination<R>, 1> s;
|
||||
for (unsigned i = 1; i <= dim (); i ++)
|
||||
{
|
||||
grading ihq = generator_grading (i);
|
||||
if (ihq.h == hq.h
|
||||
&& ihq.q == hq.q)
|
||||
{
|
||||
linear_combination<R> v (this);
|
||||
v.muladd (1, i);
|
||||
s.append (v);
|
||||
}
|
||||
}
|
||||
|
||||
mod_span<R> span (this, s);
|
||||
return submodule (span);
|
||||
}
|
||||
|
||||
template<class R> void
|
||||
module<R>::show_self () const
|
||||
{
|
||||
@ -1520,6 +1625,28 @@ mod_map<R>::induced_map (ptr<const quotient_module<R> > new_fromto)
|
||||
return new explicit_map_impl<R> (new_fromto, v);
|
||||
}
|
||||
|
||||
template<class R> mod_map<R>
|
||||
mod_map<R>::graded_piece (grading hq) const
|
||||
{
|
||||
basedvector<linear_combination<R>, 1> v (impl->from->dim ());
|
||||
for (unsigned i = 1; i <= impl->from->dim (); i ++)
|
||||
{
|
||||
grading ihq = impl->from->generator_grading (i);
|
||||
|
||||
linear_combination<R> c = column (i);
|
||||
linear_combination<R> d (impl->to);
|
||||
for (linear_combination_const_iter<R> j = c; j; j ++)
|
||||
{
|
||||
grading jhq = impl->from->generator_grading (j.key ());
|
||||
if (jhq.h - ihq.h == hq.h
|
||||
&& jhq.q - ihq.q == hq.q)
|
||||
d.muladd (j.val (), j.key ());
|
||||
}
|
||||
v[i] = d;
|
||||
}
|
||||
return mod_map (IMPL, new explicit_map_impl<R> (impl->from, impl->to, v));
|
||||
}
|
||||
|
||||
template<class R> mod_map<R>
|
||||
mod_map<R>::restrict_from (ptr<const free_submodule<R> > new_from) const
|
||||
{
|
||||
@ -1528,7 +1655,7 @@ mod_map<R>::restrict_from (ptr<const free_submodule<R> > new_from) const
|
||||
basedvector<linear_combination<R>, 1> v (new_from->dim ());
|
||||
for (unsigned i = 1; i <= new_from->dim (); i ++)
|
||||
v[i] = map (new_from->inject_generator (i));
|
||||
return new explicit_map_impl<R> (new_from, impl->to, v);
|
||||
return mod_map (IMPL, new explicit_map_impl<R> (new_from, impl->to, v));
|
||||
}
|
||||
|
||||
template<class R> mod_map<R>
|
||||
@ -1552,7 +1679,7 @@ mod_map<R>::restrict (ptr<const free_submodule<R> > new_from,
|
||||
basedvector<linear_combination<R>, 1> v (new_from->dim ());
|
||||
for (unsigned i = 1; i <= new_from->dim (); i ++)
|
||||
v[i] = new_to->restrict (map (new_from->inject_generator (i)));
|
||||
return new explicit_map_impl<R> (new_from, new_to, v);
|
||||
return mod_map (IMPL, new explicit_map_impl<R> (new_from, new_to, v));
|
||||
}
|
||||
|
||||
template<class R> linear_combination<R>
|
||||
@ -1595,7 +1722,94 @@ free_submodule<R>::restrict_submodule (ptr<const free_submodule<R> > m) const
|
||||
span[i] = restrict (m->inject_generator (i));
|
||||
|
||||
mod_span<R> span2 (this, span);
|
||||
return submodule (span2);
|
||||
return this->submodule (span2);
|
||||
}
|
||||
|
||||
template<class R> ptr<const free_submodule<R> >
|
||||
free_submodule<R>::intersection (ptr<const free_submodule<R> > m) const
|
||||
{
|
||||
assert (parent == m->parent);
|
||||
|
||||
unsigned md = m->dim (),
|
||||
d = dim ();
|
||||
|
||||
basedvector<linear_combination<R>, 1> intr;
|
||||
|
||||
basedvector<linear_combination<R>, 1> hperp,
|
||||
hproj;
|
||||
basedvector<unsigned, 1> hpivots;
|
||||
for (unsigned i = 1; i <= md; i ++)
|
||||
{
|
||||
linear_combination<R> perp (COPY, m->gens[i]),
|
||||
proj (parent);
|
||||
|
||||
for (unsigned j = 1; j <= d; j ++)
|
||||
{
|
||||
unsigned k = pivots[j];
|
||||
if (perp % k)
|
||||
{
|
||||
const linear_combination<R> &g = gens[j];
|
||||
R c = g(k);
|
||||
R d = perp(k);
|
||||
|
||||
assert (c | d);
|
||||
R q = d.div (c);
|
||||
|
||||
perp.mulsub (q, g);
|
||||
proj.mulsub (q, g);
|
||||
|
||||
assert (! (perp % k));
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned j = 1; j <= hpivots.size (); j ++)
|
||||
{
|
||||
unsigned k = hpivots[j];
|
||||
if (perp % k)
|
||||
{
|
||||
const linear_combination<R> &h = hperp[j];
|
||||
R c = h(k);
|
||||
R d = perp(k);
|
||||
|
||||
assert (c | d);
|
||||
R q = d.div (c);
|
||||
|
||||
perp.mulsub (q, h);
|
||||
proj.mulsub (q, hproj[j]);
|
||||
|
||||
assert (! (perp % k));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (perp == 0)
|
||||
intr.append (proj);
|
||||
else
|
||||
{
|
||||
hperp.append (perp);
|
||||
hproj.append (proj);
|
||||
hpivots.append (perp.head ().first);
|
||||
}
|
||||
}
|
||||
|
||||
mod_span<R> span (parent, intr);
|
||||
return parent->submodule (span);
|
||||
}
|
||||
|
||||
template<class R> ptr<const free_submodule<R> >
|
||||
free_submodule<R>::plus (ptr<const free_submodule<R> > m) const
|
||||
{
|
||||
assert (parent == m->parent);
|
||||
|
||||
basedvector<linear_combination<R>, 1> s;
|
||||
for (unsigned i = 1; i <= dim (); i ++)
|
||||
s.append (gens[i]);
|
||||
|
||||
for (unsigned i = 1; i <= m->dim (); i ++)
|
||||
s.append (m->gens[i]);
|
||||
|
||||
mod_span<R> span (parent, s);
|
||||
return parent->submodule (span);
|
||||
}
|
||||
|
||||
template<class R> bool
|
||||
@ -1628,6 +1842,14 @@ mod_map<R>::check_grading (grading delta) const
|
||||
}
|
||||
}
|
||||
|
||||
template<class R> mod_map<R>
|
||||
mod_map<R>::operator * (const R &c) const
|
||||
{
|
||||
basedvector<linear_combination<R>, 1> v (impl->from->dim ());
|
||||
for (unsigned i = 1; i <= impl->from->dim (); i ++)
|
||||
v[i] = c*column (i);
|
||||
return mod_map (IMPL, new explicit_map_impl<R> (impl->from, impl->to, v));
|
||||
}
|
||||
|
||||
template<class R> mod_map<R>
|
||||
mod_map<R>::operator + (const mod_map &m) const
|
||||
@ -1636,8 +1858,8 @@ mod_map<R>::operator + (const mod_map &m) const
|
||||
|
||||
basedvector<linear_combination<R>, 1> v (impl->from->dim ());
|
||||
for (unsigned i = 1; i <= m.impl->from->dim (); i ++)
|
||||
v[i] = column (i) + m.columns (i);
|
||||
return explicit_map_impl<R> (impl->from, impl->to, v);
|
||||
v[i] = column (i) + m.column (i);
|
||||
return mod_map (IMPL, new explicit_map_impl<R> (impl->from, impl->to, v));
|
||||
}
|
||||
|
||||
template<class R> ptr<const free_submodule<R> >
|
||||
@ -1647,7 +1869,7 @@ mod_map<R>::kernel () const
|
||||
to = impl->to;
|
||||
|
||||
basedvector<linear_combination<R>, 1> from_xs (from->dim ());
|
||||
for (unsigned i = 1; i <= to->dim (); i ++)
|
||||
for (unsigned i = 1; i <= from->dim (); i ++)
|
||||
{
|
||||
linear_combination<R> x (from);
|
||||
x.muladd (1, i);
|
||||
@ -1670,13 +1892,21 @@ mod_map<R>::kernel () const
|
||||
linear_combination<R> &to_x = to_xs[j],
|
||||
&from_x = from_xs[j];
|
||||
R to_xc = to_x(i);
|
||||
if (! (to_vc | to_xc))
|
||||
if (to_xc == 0)
|
||||
continue;
|
||||
|
||||
if (to_vc == 0 && to_xc != 0)
|
||||
{
|
||||
triple<R, R, R> t = to_vc.extended_gcd (to_xc);
|
||||
assert (t.first == to_vc*t.second + t.third*to_xc);
|
||||
to_v += to_x;
|
||||
from_v += from_x;
|
||||
}
|
||||
else if (! (to_vc | to_xc))
|
||||
{
|
||||
tuple<R, R, R> t = to_vc.extended_gcd (to_xc);
|
||||
assert (get<0> (t) == to_vc*get<1> (t) + get<2> (t)*to_xc);
|
||||
|
||||
to_v = t.second*to_v + t.third*to_x;
|
||||
from_v = t.second*from_v + t.third*from_x;
|
||||
to_v = get<1> (t)*to_v + get<2> (t)*to_x;
|
||||
from_v = get<1> (t)*from_v + get<2> (t)*from_x;
|
||||
|
||||
assert (to_v(i) != 0);
|
||||
}
|
||||
@ -1715,6 +1945,15 @@ mod_map<R>::image () const
|
||||
return impl->to->submodule (span);
|
||||
}
|
||||
|
||||
template<class R> ptr<const free_submodule<R> >
|
||||
mod_map<R>::image (basedvector<linear_combination<R>, 1> vs) const
|
||||
{
|
||||
mod_span<R> span (impl->from, vs);
|
||||
ptr<const free_submodule<R> > s = impl->from->submodule (span);
|
||||
mod_map<R> r = restrict_from (s);
|
||||
return r.image ();
|
||||
}
|
||||
|
||||
template<class R> ptr<const quotient_module<R> >
|
||||
mod_map<R>::cokernel () const
|
||||
{
|
||||
@ -1767,13 +2006,19 @@ mod_span<R>::mod_span (ptr<const module<R> > mod,
|
||||
|
||||
linear_combination<R> &x = xs[j];
|
||||
R xc = x(i);
|
||||
if (xc == 0)
|
||||
continue;
|
||||
|
||||
if (! (vc | xc))
|
||||
if (vc == 0)
|
||||
{
|
||||
triple<R, R, R> t = vc.extended_gcd (xc);
|
||||
assert (t.first == vc*t.second + t.third*xc);
|
||||
v += x;
|
||||
}
|
||||
else if (! (vc | xc))
|
||||
{
|
||||
tuple<R, R, R> t = vc.extended_gcd (xc);
|
||||
assert (get<0> (t) == vc*get<1> (t) + get<2> (t)*xc);
|
||||
|
||||
v = t.second*v + t.third*x;
|
||||
v = get<1> (t)*v + get<2> (t)*x;
|
||||
|
||||
assert (v(i) != 0);
|
||||
}
|
||||
@ -1820,8 +2065,68 @@ mod_map<R>::display_self () const
|
||||
{
|
||||
printf (" %d ", i);
|
||||
impl->from->show_generator (i);
|
||||
printf (" ");
|
||||
show (impl->from->generator_grading (i));
|
||||
printf (": ");
|
||||
show (column (i));
|
||||
newline ();
|
||||
}
|
||||
}
|
||||
|
||||
// ??? io
|
||||
|
||||
template<class R> void
|
||||
writer::write_mod (ptr<const module<R> > m)
|
||||
{
|
||||
pair<unsigned &, bool> p = aw->id_io_id.find (m->id);
|
||||
if (p.second)
|
||||
{
|
||||
write_int ((int)p.first);
|
||||
}
|
||||
else
|
||||
{
|
||||
++ aw->io_id_counter;
|
||||
unsigned io_id = aw->io_id_counter;
|
||||
|
||||
p.first = io_id;
|
||||
|
||||
write_int (- (int)io_id);
|
||||
|
||||
unsigned n = m->dim (),
|
||||
r = m->free_rank ();
|
||||
write_unsigned (n);
|
||||
write_unsigned (r);
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
write (*this, m->generator_grading (i));
|
||||
for (unsigned i = r + 1; i <= n; i ++)
|
||||
write (*this, m->generator_ann (i));
|
||||
}
|
||||
}
|
||||
|
||||
template<class R> ptr<const module<R> >
|
||||
reader::read_mod ()
|
||||
{
|
||||
int io_id = read_int ();
|
||||
if (io_id < 0)
|
||||
{
|
||||
unsigned n = read_unsigned ();
|
||||
unsigned r = read_unsigned ();
|
||||
basedvector<grading, 1> gr (n);
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
gr[i] = grading (*this);
|
||||
basedvector<R, 1> ann (n - r);
|
||||
for (unsigned i = r + 1; i <= n; i ++)
|
||||
ann[i - r] = R (*this);
|
||||
|
||||
ptr<const module<R> > m = new explicit_module<R> (r, ann, gr);
|
||||
ar->io_id_id.push ((unsigned)(-io_id), m->id);
|
||||
module<R>::reader_id_module.push (m->id, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned id = ar->io_id_id(io_id);
|
||||
return module<R>::reader_id_module(id);
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ class multivariate_laurent_monomial
|
||||
#endif
|
||||
return m == e.m;
|
||||
}
|
||||
bool operator != (const multivariate_laurent_monomial &e) const { return !operator == (e); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
@ -204,6 +205,12 @@ class multivariate_laurentpoly
|
||||
coeffs.push (monomial (VARIABLE, i), c);
|
||||
}
|
||||
|
||||
multivariate_laurentpoly (T c, variable, unsigned i, int e)
|
||||
{
|
||||
if (c != 0)
|
||||
coeffs.push (monomial (VARIABLE, i, e), c);
|
||||
}
|
||||
|
||||
multivariate_laurentpoly (T c, const monomial &m)
|
||||
{
|
||||
if (c != 0)
|
||||
@ -212,7 +219,8 @@ class multivariate_laurentpoly
|
||||
|
||||
multivariate_laurentpoly (const multivariate_laurentpoly &p) : coeffs(p.coeffs) { }
|
||||
multivariate_laurentpoly (copy, const multivariate_laurentpoly &p)
|
||||
: coeffs(COPY2, p.coeffs)
|
||||
// ??? COPY2?
|
||||
: coeffs(COPY, p.coeffs)
|
||||
{
|
||||
}
|
||||
|
||||
@ -243,6 +251,7 @@ class multivariate_laurentpoly
|
||||
#endif
|
||||
return coeffs == p.coeffs;
|
||||
}
|
||||
bool operator != (const multivariate_laurentpoly &p) const { return !operator == (p); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
template<unsigned n>
|
||||
class multivariate_monomial
|
||||
{
|
||||
private:
|
||||
public:
|
||||
unsigned v[n];
|
||||
|
||||
public:
|
||||
@ -56,6 +56,7 @@ class multivariate_monomial
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bool operator != (const multivariate_monomial &e) const { return !operator == (e); }
|
||||
|
||||
bool operator < (const multivariate_monomial &e) const
|
||||
{
|
||||
@ -199,7 +200,7 @@ public:
|
||||
|
||||
bool is_unit () const;
|
||||
|
||||
bool operator == (multivariate_polynomial p) const
|
||||
bool operator == (const multivariate_polynomial &p) const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
check ();
|
||||
@ -207,6 +208,7 @@ public:
|
||||
#endif
|
||||
return coeffs == p.coeffs;
|
||||
}
|
||||
bool operator != (const multivariate_polynomial &p) const { return !operator == (p); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
@ -263,6 +265,12 @@ public:
|
||||
|
||||
monomial common_monomial () const;
|
||||
|
||||
multivariate_polynomial gcd (const multivariate_polynomial &b) const
|
||||
{
|
||||
// ???
|
||||
return multivariate_polynomial (1);
|
||||
}
|
||||
|
||||
pair<multivariate_polynomial, multivariate_polynomial>
|
||||
uncommon_factors (multivariate_polynomial b, basedvector<multivariate_polynomial, 1> ds);
|
||||
maybe<multivariate_polynomial>
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
|
||||
polynomial (const polynomial &p) : coeffs(p.coeffs) { }
|
||||
polynomial (copy, const polynomial &p) : coeffs(COPY, p.coeffs) { }
|
||||
polynomial (reader &r) : coeffs(r) { }
|
||||
~polynomial () { }
|
||||
|
||||
polynomial &operator = (const polynomial &p) { coeffs = p.coeffs; return *this; }
|
||||
@ -64,7 +65,16 @@ public:
|
||||
unsigned degree () const;
|
||||
bool is_unit () const;
|
||||
|
||||
bool operator == (polynomial p) const
|
||||
polynomial recip () const
|
||||
{
|
||||
assert (coeffs.card () == 1);
|
||||
|
||||
pair<unsigned, T> p = coeffs.head ();
|
||||
assert (p.first == 0);
|
||||
return polynomial (p.second.recip ());
|
||||
}
|
||||
|
||||
bool operator == (const polynomial &p) const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
check ();
|
||||
@ -72,6 +82,7 @@ public:
|
||||
#endif
|
||||
return coeffs == p.coeffs;
|
||||
}
|
||||
bool operator != (const polynomial &p) const { return !operator == (p); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
@ -95,6 +106,7 @@ public:
|
||||
polynomial &operator *= (polynomial p) { return operator = (*this * p); }
|
||||
polynomial &operator *= (T s);
|
||||
|
||||
// ??? rename
|
||||
polynomial &add_term (T c, unsigned e)
|
||||
{
|
||||
T &c2 = coeffs[e];
|
||||
@ -112,27 +124,36 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
polynomial operator - (polynomial p) const
|
||||
polynomial operator - (const polynomial &p) const
|
||||
{
|
||||
polynomial r (COPY, *this);
|
||||
r -= p;
|
||||
return r;
|
||||
}
|
||||
|
||||
polynomial operator * (polynomial p) const;
|
||||
polynomial operator * (const polynomial &p) const;
|
||||
|
||||
pair<polynomial, polynomial> divide_with_remainder (polynomial d) const;
|
||||
bool divides (const polynomial &num) const;
|
||||
|
||||
polynomial mod (polynomial d) const;
|
||||
bool divides (polynomial d) const;
|
||||
polynomial divide_exact (polynomial d) const;
|
||||
// *this | num
|
||||
bool operator | (const polynomial &num) const { return divides (num); }
|
||||
|
||||
polynomial gcd (polynomial b) const;
|
||||
tuple<polynomial, polynomial> divide_with_remainder (const polynomial &denom) const;
|
||||
|
||||
polynomial mod (const polynomial &denom) const;
|
||||
|
||||
polynomial divide_exact (const polynomial &denom) const;
|
||||
polynomial div (const polynomial &denom) const { return divide_exact (denom); }
|
||||
|
||||
polynomial gcd (const polynomial &b) const;
|
||||
polynomial lcm (const polynomial &b) const;
|
||||
tuple<polynomial, polynomial, polynomial> extended_gcd (const polynomial &b) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check () const;
|
||||
#endif
|
||||
|
||||
void write_self (writer &w) const { write (w, coeffs); }
|
||||
static void show_ring () { T::show_ring (); printf ("[x]"); }
|
||||
void display_self () const { show_self (); newline (); }
|
||||
void show_self () const;
|
||||
@ -197,7 +218,7 @@ polynomial<T>::operator *= (T s)
|
||||
}
|
||||
|
||||
template<class T> polynomial<T>
|
||||
polynomial<T>::operator * (polynomial p) const
|
||||
polynomial<T>::operator * (const polynomial &p) const
|
||||
{
|
||||
polynomial r;
|
||||
|
||||
@ -213,14 +234,15 @@ polynomial<T>::operator * (polynomial p) const
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class T> pair<polynomial<T>, polynomial<T> >
|
||||
polynomial<T>::divide_with_remainder (polynomial d) const
|
||||
template<class T> tuple<polynomial<T>, polynomial<T> >
|
||||
polynomial<T>::divide_with_remainder (const polynomial &d) const
|
||||
{
|
||||
// num = *this
|
||||
assert (d != 0);
|
||||
|
||||
polynomial r (COPY, *this);
|
||||
polynomial q;
|
||||
|
||||
|
||||
pair<unsigned, T> d_leading_term = d.coeffs.tail ();
|
||||
for (;;)
|
||||
{
|
||||
@ -240,45 +262,80 @@ polynomial<T>::divide_with_remainder (polynomial d) const
|
||||
assert (r == 0 || r.degree () < d.degree ());
|
||||
// assert (*this == q*d + r);
|
||||
|
||||
return pair<polynomial, polynomial> (q, r);
|
||||
return make_tuple (q, r);
|
||||
}
|
||||
|
||||
template<class T> polynomial<T>
|
||||
polynomial<T>::mod (polynomial d) const
|
||||
polynomial<T>::mod (const polynomial &denom) const
|
||||
{
|
||||
pair<polynomial<T>, polynomial<T> > qr = divide_with_remainder (d);
|
||||
return qr.second;
|
||||
polynomial q, r;
|
||||
tie (q, r) = divide_with_remainder (denom);
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class T> bool
|
||||
polynomial<T>::divides (polynomial d) const
|
||||
polynomial<T>::divides (const polynomial &num) const
|
||||
{
|
||||
pair<polynomial<T>, polynomial<T> > qr = divide_with_remainder (d);
|
||||
return qr.second == 0;
|
||||
// denom = *this
|
||||
polynomial q, r;
|
||||
tie (q, r) = num.divide_with_remainder (*this);
|
||||
return r == 0;
|
||||
}
|
||||
|
||||
template<class T> polynomial<T>
|
||||
polynomial<T>::divide_exact (polynomial d) const
|
||||
polynomial<T>::divide_exact (const polynomial &denom) const
|
||||
{
|
||||
pair<polynomial<T>, polynomial<T> > qr = divide_with_remainder (d);
|
||||
assert (qr.second == 0);
|
||||
return qr.first;
|
||||
polynomial q, r;
|
||||
tie (q, r) = divide_with_remainder (denom);
|
||||
assert (r == 0);
|
||||
return q;
|
||||
}
|
||||
|
||||
template<class T> polynomial<T>
|
||||
polynomial<T>::gcd (polynomial b) const
|
||||
polynomial<T>::gcd (const polynomial &b) const
|
||||
{
|
||||
polynomial a = *this;
|
||||
|
||||
while (b != 0)
|
||||
{
|
||||
pair<polynomial<T>, polynomial<T> > a_qr = a.divide_with_remainder (b);
|
||||
polynomial r;
|
||||
tie (ignore, r) = a.divide_with_remainder (b);
|
||||
a = b;
|
||||
b = a_qr.second;
|
||||
b = r;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
template<class T> polynomial<T>
|
||||
polynomial<T>::lcm (const polynomial &b) const
|
||||
{
|
||||
// a = *this
|
||||
return divide_exact (gcd (b)) * b;
|
||||
}
|
||||
|
||||
template<class T> tuple<polynomial<T>, polynomial<T>, polynomial<T> >
|
||||
polynomial<T>::extended_gcd (const polynomial &b) const
|
||||
{
|
||||
// a = *this
|
||||
if (b == 0)
|
||||
return make_tuple (*this, polynomial (1), polynomial (0));
|
||||
|
||||
polynomial q, r;
|
||||
tie (q, r) = divide_with_remainder (b);
|
||||
if (r == 0)
|
||||
return make_tuple (b, polynomial (0), polynomial (1));
|
||||
else
|
||||
{
|
||||
polynomial d, s, t;
|
||||
|
||||
tie (d, s, t) = b.extended_gcd (r);
|
||||
|
||||
polynomial s2 = t,
|
||||
t2 = s - t*q;
|
||||
|
||||
return make_tuple (d, s2, t2);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<class T> void
|
||||
polynomial<T>::check () const
|
||||
@ -338,14 +395,14 @@ class polynomial<Z2>
|
||||
|
||||
public:
|
||||
polynomial () { }
|
||||
explicit polynomial (int x)
|
||||
polynomial (int x)
|
||||
{
|
||||
Z2 c (x);
|
||||
if (c != 0)
|
||||
coeffs.push (0);
|
||||
}
|
||||
|
||||
explicit polynomial (Z2 c)
|
||||
polynomial (Z2 c)
|
||||
{
|
||||
if (c != 0)
|
||||
coeffs.push (0);
|
||||
@ -380,7 +437,8 @@ class polynomial<Z2>
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator == (polynomial p) const { return coeffs == p.coeffs; }
|
||||
bool operator == (const polynomial &p) const { return coeffs == p.coeffs; }
|
||||
bool operator != (const polynomial &p) const { return !operator == (p); }
|
||||
|
||||
bool operator == (int x) const
|
||||
{
|
||||
@ -395,6 +453,17 @@ class polynomial<Z2>
|
||||
bool operator != (int x) const { return !operator == (x); }
|
||||
|
||||
unsigned degree () const { return coeffs.tail (); }
|
||||
bool is_unit () const
|
||||
{
|
||||
return coeffs.card () == 1
|
||||
&& coeffs.head () == 0;
|
||||
}
|
||||
|
||||
polynomial recip () const
|
||||
{
|
||||
assert (is_unit ());
|
||||
return 1;
|
||||
}
|
||||
|
||||
polynomial &operator += (polynomial p) { coeffs ^= p.coeffs; return *this; }
|
||||
polynomial &operator -= (polynomial p) { coeffs ^= p.coeffs; return *this; }
|
||||
@ -443,4 +512,3 @@ class polynomial<Z2>
|
||||
void display_self () const { show_self (); newline (); }
|
||||
void show_self () const;
|
||||
};
|
||||
|
||||
|
@ -19,10 +19,10 @@ public:
|
||||
|
||||
public:
|
||||
rd_unify ();
|
||||
rd_unify (const rd_unify &); // doesn't exist
|
||||
rd_unify (const rd_unify &) = delete;
|
||||
~rd_unify () { }
|
||||
|
||||
rd_unify &operator = (const rd_unify &); // doesn't exist
|
||||
rd_unify &operator = (const rd_unify &) = delete;
|
||||
|
||||
bool unify (const resolution_diagram &rd1, const resolution_diagram &rd2);
|
||||
unsigned map_starting_monomial (unsigned m);
|
||||
|
@ -160,6 +160,7 @@ class resolution_diagram
|
||||
resolution_diagram &operator = (const resolution_diagram &rd);
|
||||
|
||||
bool operator == (const resolution_diagram &rd) const;
|
||||
bool operator != (const resolution_diagram &rd) const { return !operator == (rd); }
|
||||
|
||||
/* reverse, reverse_orientation leave starting/ending circle numbers
|
||||
unchanged. */
|
||||
@ -190,10 +191,10 @@ class resolution_diagram_builder
|
||||
|
||||
public:
|
||||
resolution_diagram_builder ();
|
||||
resolution_diagram_builder (const resolution_diagram_builder &); // doesn't exist
|
||||
resolution_diagram_builder (const resolution_diagram_builder &) = delete;
|
||||
~resolution_diagram_builder () { }
|
||||
|
||||
resolution_diagram_builder &operator = (const resolution_diagram_builder &); // doesn't exist
|
||||
resolution_diagram_builder &operator = (const resolution_diagram_builder &) = delete;
|
||||
|
||||
void init (const knot_diagram &d,
|
||||
smallbitset from_state, const smoothing &from_s,
|
||||
|
17
cube.h
17
cube.h
@ -3,10 +3,10 @@ class map_rules
|
||||
{
|
||||
public:
|
||||
map_rules () { }
|
||||
map_rules (const map_rules &); // doesn't exist
|
||||
map_rules (const map_rules &) = delete;
|
||||
virtual ~map_rules () { }
|
||||
|
||||
map_rules &operator = (const map_rules &); // doesn't exist
|
||||
map_rules &operator = (const map_rules &) = delete;
|
||||
|
||||
virtual void map (basedvector<pair<unsigned, unsigned>, 1> &out,
|
||||
resolution_diagram_builder &rdb) const = 0;
|
||||
@ -16,8 +16,8 @@ template<class R>
|
||||
class cube /* of resolutions */
|
||||
{
|
||||
public:
|
||||
typedef typename R::linear_combination linear_combination;
|
||||
typedef typename R::linear_combination_const_iter linear_combination_const_iter;
|
||||
typedef ::linear_combination<R> linear_combination;
|
||||
typedef ::linear_combination_const_iter<R> linear_combination_const_iter;
|
||||
|
||||
public:
|
||||
bool markedp_only;
|
||||
@ -47,6 +47,7 @@ public:
|
||||
bool reverse_orientation,
|
||||
unsigned to_reverse) const;
|
||||
|
||||
mod_map<R> compute_dinv (unsigned c);
|
||||
mod_map<R> H_i (unsigned c);
|
||||
|
||||
mod_map<R> compute_nu () const;
|
||||
@ -77,10 +78,10 @@ class twisted_map_rules
|
||||
{
|
||||
public:
|
||||
twisted_map_rules () { }
|
||||
twisted_map_rules (const twisted_map_rules &); // doesn't exist
|
||||
twisted_map_rules (const twisted_map_rules &) = delete;
|
||||
virtual ~twisted_map_rules () { }
|
||||
|
||||
map_rules &operator = (const twisted_map_rules &); // doesn't exist
|
||||
map_rules &operator = (const twisted_map_rules &) = delete;
|
||||
|
||||
virtual void map (basedvector<triple<unsigned, unsigned, set<unsigned> >, 1> &out,
|
||||
resolution_diagram_builder &rdb) const = 0;
|
||||
@ -100,10 +101,10 @@ class twisted_cube
|
||||
: c(c_)
|
||||
{ }
|
||||
|
||||
twisted_cube (const twisted_cube &); // doesn't exist
|
||||
twisted_cube (const twisted_cube &) = delete;
|
||||
~twisted_cube () { }
|
||||
|
||||
twisted_cube &operator = (const twisted_cube &); // doesn't exist
|
||||
twisted_cube &operator = (const twisted_cube &) = delete;
|
||||
|
||||
mod_map<R> compute_twisted_map (basedvector<int, 1> edge_weight,
|
||||
unsigned dh,
|
||||
|
185
cube_impl.h
185
cube_impl.h
@ -9,7 +9,7 @@ public:
|
||||
khC_generators (const cube<R> &c_) : c(c_) { }
|
||||
~khC_generators () { }
|
||||
|
||||
khC_generators &operator = (const khC_generators &); // doesn't exist
|
||||
khC_generators &operator = (const khC_generators &) = delete;
|
||||
|
||||
unsigned dim () const { return c.n_generators; }
|
||||
unsigned free_rank () const { return c.n_generators; }
|
||||
@ -166,7 +166,7 @@ cube<R>::compute_map (unsigned dh, unsigned max_n,
|
||||
continue;
|
||||
assert (!unsigned_bittest (v_to, p));
|
||||
}
|
||||
|
||||
|
||||
b[generator (fromstate, v_from)].muladd
|
||||
(sign, generator (tostate, v_to));
|
||||
}
|
||||
@ -187,10 +187,10 @@ class d_rules : public map_rules
|
||||
{
|
||||
public:
|
||||
d_rules () { }
|
||||
d_rules (const d_rules &); // doesn't exist
|
||||
d_rules (const d_rules &) = delete;
|
||||
~d_rules () { }
|
||||
|
||||
d_rules &operator = (const d_rules &); // doesn't exist
|
||||
d_rules &operator = (const d_rules &) = delete;
|
||||
|
||||
void map (basedvector<pair<unsigned, unsigned>, 1> &out,
|
||||
resolution_diagram_builder &rdb) const
|
||||
@ -214,10 +214,10 @@ class twin_arrows_P_rules : public map_rules
|
||||
{
|
||||
public:
|
||||
twin_arrows_P_rules () { }
|
||||
twin_arrows_P_rules (const twin_arrows_P_rules &); // doesn't exist
|
||||
twin_arrows_P_rules (const twin_arrows_P_rules &) = delete;
|
||||
~twin_arrows_P_rules () { }
|
||||
|
||||
twin_arrows_P_rules &operator = (const twin_arrows_P_rules &); // doesn't exist
|
||||
twin_arrows_P_rules &operator = (const twin_arrows_P_rules &) = delete;
|
||||
|
||||
void map (basedvector<pair<unsigned, unsigned>, 1> &out,
|
||||
resolution_diagram_builder &rdb) const
|
||||
@ -302,7 +302,7 @@ cube<R>::compute_X (unsigned p) const
|
||||
template<class R> mod_map<R>
|
||||
cube<R>::H_i (unsigned c)
|
||||
{
|
||||
mod_map<R> b (khC, 0);
|
||||
map_builder<R> b (khC, 0);
|
||||
for (unsigned i = 0; i < n_resolutions; i ++)
|
||||
{
|
||||
if (unsigned_bittest (i, c))
|
||||
@ -319,8 +319,23 @@ cube<R>::H_i (unsigned c)
|
||||
|
||||
unsigned from = from_s.crossing_from_circle (kd, c),
|
||||
to = from_s.crossing_to_circle (kd, c);
|
||||
|
||||
int sign = 1;
|
||||
for (unsigned j = 1; j < c; j ++)
|
||||
{
|
||||
if (unsigned_bittest (i, j))
|
||||
sign *= -1;
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < from_s.num_monomials (); j ++)
|
||||
{
|
||||
if (markedp_only)
|
||||
{
|
||||
unsigned p = from_s.edge_circle[kd.marked_edge];
|
||||
if (unsigned_bittest (j, p))
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned j2 = 0;
|
||||
for (unsigned_const_iter k = j; k; k ++)
|
||||
{
|
||||
@ -336,7 +351,7 @@ cube<R>::H_i (unsigned c)
|
||||
to_s.crossing_from_circle (kd, c));
|
||||
j2 = unsigned_bitset (j2,
|
||||
to_s.crossing_to_circle (kd, c));
|
||||
v.muladd (1, generator (i2, j2));
|
||||
v.muladd (-sign, generator (i2, j2));
|
||||
}
|
||||
else if (from != to
|
||||
&& !unsigned_bittest (j, from)
|
||||
@ -344,7 +359,7 @@ cube<R>::H_i (unsigned c)
|
||||
{
|
||||
assert (! unsigned_bittest (j2,
|
||||
to_s.crossing_from_circle (kd, c)));
|
||||
v.muladd (1, generator (i2, j2));
|
||||
v.muladd (sign, generator (i2, j2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -356,6 +371,110 @@ cube<R>::H_i (unsigned c)
|
||||
return H_c;
|
||||
}
|
||||
|
||||
template<class R> mod_map<R>
|
||||
cube<R>::compute_dinv (unsigned c)
|
||||
{
|
||||
map_builder<R> p (khC);
|
||||
for (unsigned i = 0; i < n_resolutions; i ++)
|
||||
{
|
||||
if (!unsigned_bittest (i, c))
|
||||
continue;
|
||||
|
||||
int sign = 1;
|
||||
for (unsigned j = 1; j < c; j ++)
|
||||
{
|
||||
if (unsigned_bittest (i, j))
|
||||
sign *= -1;
|
||||
}
|
||||
|
||||
smoothing from_s (kd, smallbitset (n_crossings, i));
|
||||
|
||||
unsigned i2 = unsigned_bitclear (i, c);
|
||||
smoothing to_s (kd, smallbitset (n_crossings, i2));
|
||||
|
||||
basedvector<unsigned, 1> from_circle_edge_rep (from_s.n_circles);
|
||||
for (unsigned j = 1; j <= kd.num_edges (); j ++)
|
||||
from_circle_edge_rep[from_s.edge_circle[j]] = j;
|
||||
|
||||
unsigned a = from_s.crossing_from_circle (kd, c),
|
||||
b = from_s.crossing_to_circle (kd, c);
|
||||
unsigned x = to_s.crossing_from_circle (kd, c),
|
||||
y = to_s.crossing_to_circle (kd, c);
|
||||
for (unsigned j = 0; j < from_s.num_monomials (); j ++)
|
||||
{
|
||||
if (markedp_only)
|
||||
{
|
||||
unsigned p = from_s.edge_circle[kd.marked_edge];
|
||||
if (unsigned_bittest (j, p))
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned j2 = 0;
|
||||
for (unsigned_const_iter k = j; k; k ++)
|
||||
{
|
||||
unsigned s = k.val ();
|
||||
j2 = unsigned_bitset (j2, to_s.edge_circle[from_circle_edge_rep[s]]);
|
||||
}
|
||||
|
||||
if (a == b)
|
||||
{
|
||||
// split
|
||||
assert (x != y);
|
||||
|
||||
if (unsigned_bittest (j, a))
|
||||
{
|
||||
// 1 -> x + y
|
||||
j2 = unsigned_bitset (j2, x);
|
||||
j2 = unsigned_bitclear (j2, y);
|
||||
|
||||
p[generator (i, j)].muladd (sign, generator (i2, j2));
|
||||
|
||||
j2 = unsigned_bitclear (j2, x);
|
||||
j2 = unsigned_bitset (j2, y);
|
||||
|
||||
p[generator (i, j)].muladd (sign, generator (i2, j2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// a -> xy
|
||||
j2 = unsigned_bitclear (j2, x);
|
||||
j2 = unsigned_bitclear (j2, y);
|
||||
|
||||
p[generator (i, j)].muladd (sign, generator (i2, j2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// join
|
||||
assert (x == y);
|
||||
|
||||
if (unsigned_bittest (j, a)
|
||||
&& unsigned_bittest (j, b))
|
||||
{
|
||||
// 1 -> 1
|
||||
j2 = unsigned_bitset (j2, x);
|
||||
|
||||
p[generator (i, j)].muladd (sign, generator (i2, j2));
|
||||
}
|
||||
else if ((unsigned_bittest (j, a)
|
||||
&& !unsigned_bittest (j, b))
|
||||
|| (!unsigned_bittest (j, a)
|
||||
&& unsigned_bittest (j, b)))
|
||||
{
|
||||
// a, b -> x
|
||||
j2 = unsigned_bitclear (j2, x);
|
||||
|
||||
p[generator (i, j)].muladd (sign, generator (i2, j2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod_map<R> dinv (p);
|
||||
dinv.check_grading (grading (-1, -2));
|
||||
return dinv;
|
||||
}
|
||||
|
||||
template<class R> void
|
||||
cube<R>::check_reverse_crossings ()
|
||||
{
|
||||
@ -415,6 +534,50 @@ cube<R>::cube (knot_diagram &kd_, bool markedp_only_)
|
||||
{
|
||||
smallbitset state (n_crossings, i);
|
||||
s.init (kd, state);
|
||||
|
||||
#if 1
|
||||
unsigned fromstate = i;
|
||||
smoothing &from_s = s;
|
||||
|
||||
unsigned n_zerocrossings = n_crossings - unsigned_bitcount (fromstate);
|
||||
unsigned n_cobordisms = ((unsigned)1) << n_zerocrossings;
|
||||
for (unsigned j = 0; j < n_cobordisms; j ++)
|
||||
{
|
||||
unsigned tostate = unsigned_pack (n_crossings, fromstate, j);
|
||||
unsigned crossings = tostate & ~fromstate;
|
||||
|
||||
smoothing to_s (kd, smallbitset (n_crossings, tostate));
|
||||
|
||||
set<unsigned> starting_circles,
|
||||
ending_circles;
|
||||
for (unsigned_const_iter k = crossings; k; k ++)
|
||||
{
|
||||
unsigned c = k.val ();
|
||||
|
||||
unsigned starting_from = s.ept_circle (kd, kd.crossings[c][2]),
|
||||
starting_to = s.ept_circle (kd, kd.crossings[c][4]);
|
||||
starting_circles += starting_from;
|
||||
starting_circles += starting_to;
|
||||
|
||||
unsigned ending_from = to_s.ept_circle (kd, kd.crossings[c][2]),
|
||||
ending_to = to_s.ept_circle (kd, kd.crossings[c][4]);
|
||||
ending_circles += ending_from;
|
||||
ending_circles += ending_to;
|
||||
}
|
||||
if (starting_circles.card () == 1
|
||||
&& ending_circles.card () == 1)
|
||||
{
|
||||
unsigned k = unsigned_bitcount (crossings);
|
||||
|
||||
#if 0
|
||||
s.show_self (kd, state);
|
||||
printf (" crossings "); show (smallbitset (n_crossings, crossings));
|
||||
newline ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
resolution_circles[i] = s.n_circles;
|
||||
resolution_generator1[i] = n_generators + 1;
|
||||
n_generators += s.num_generators (markedp_only);
|
||||
@ -676,10 +839,10 @@ class twisted_barE_rules : public twisted_map_rules
|
||||
{
|
||||
public:
|
||||
twisted_barE_rules () { }
|
||||
twisted_barE_rules (const twisted_barE_rules &); // doesn't exist
|
||||
twisted_barE_rules (const twisted_barE_rules &) = delete;
|
||||
~twisted_barE_rules () { }
|
||||
|
||||
twisted_barE_rules &operator = (const twisted_barE_rules &); // doesn't exist
|
||||
twisted_barE_rules &operator = (const twisted_barE_rules &) = delete;
|
||||
|
||||
void map (basedvector<triple<unsigned, unsigned, set<unsigned> >, 1> &out,
|
||||
resolution_diagram_builder &rdb) const
|
||||
|
126
gss.cpp
126
gss.cpp
@ -1,126 +0,0 @@
|
||||
|
||||
#include <knotkit.h>
|
||||
|
||||
const char *program_name;
|
||||
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
printf ("usage: %s [-f] [-h] [-o <file>] [-v] <knot>\n", program_name);
|
||||
printf (" compute Szabo's geometric spectral sequence for knot <knot>\n");
|
||||
printf ("options:\n");
|
||||
printf (" -f : compute unreduced spectral sequence\n");
|
||||
printf (" (reduced is the default)\n");
|
||||
printf (" -h : print this message\n");
|
||||
printf (" -o <file> : write output to <file>\n");
|
||||
printf (" (stdout is the default)\n");
|
||||
printf (" -v : verbose: report progress as the computation proceeds\n");
|
||||
printf ("<knot> can be one of:\n");
|
||||
printf (" - the unknot, e.g. U or unknot\n");
|
||||
printf (" - a torus knot, e.g. T(2,3)\n");
|
||||
printf (" - a Rolfsen table knot, e.g. 10_124\n");
|
||||
printf (" - a Hoste-Thistlethwaite-Weeks knot, e.g. 11a12 or 12n214\n");
|
||||
printf (" - a Morwen Thistlethwaite link, e.g. L9a21 or L14n7631\n");
|
||||
printf (" - a planar diagram, e.g.\n");
|
||||
printf (" PD[X[1, 4, 2, 5], X[3, 6, 4, 1], X[5, 2, 6, 3]] or\n");
|
||||
printf (" PD[[1, 4, 2, 5], [3, 6, 4, 1], [5, 2, 6, 3]]\n");
|
||||
printf (" - a Dowker-Thistlethwaite code, e.g.\n");
|
||||
printf (" DTCode[6,8,2,4],\n");
|
||||
printf (" DT[dadbcda] or\n");
|
||||
printf (" DT[{6, -8}, {-10, 12, -14, 2, -4}]\n");
|
||||
printf (" - a braid, e.g. BR[2, {-1, -1, -1}]\n");
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
program_name = argv[0];
|
||||
|
||||
bool reduced = 1;
|
||||
const char *knot = 0;
|
||||
const char *file = 0;
|
||||
|
||||
for (int i = 1; i < argc; i ++)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
if (strcmp (argv[i], "-f") == 0)
|
||||
reduced = 0;
|
||||
else if (strcmp (argv[i], "-h") == 0)
|
||||
{
|
||||
usage ();
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
else if (!strcmp (argv[i], "-v"))
|
||||
verbose = 1;
|
||||
else if (!strcmp (argv[i], "-o"))
|
||||
{
|
||||
i ++;
|
||||
if (i == argc)
|
||||
{
|
||||
fprintf (stderr, "error: missing argument to option `-o'\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
file = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: unknown argument `%s'\n", argv[1]);
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (knot)
|
||||
{
|
||||
fprintf (stderr, "error: too many arguments\n");
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
knot = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!knot)
|
||||
{
|
||||
fprintf (stderr, "error: missing <knot> argument\n");
|
||||
usage ();
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
FILE *outfp = 0;
|
||||
if (file)
|
||||
{
|
||||
outfp = fopen (file, "w");
|
||||
if (!outfp)
|
||||
{
|
||||
stderror ("fopen: %s", file);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
outfp = stdout;
|
||||
|
||||
knot_diagram d = parse_knot (knot);
|
||||
d.marked_edge = 1;
|
||||
cube<Z2> c (d, reduced);
|
||||
|
||||
fprintf (outfp, "\\documentclass{article}\n\
|
||||
\\usepackage{amsmath, tikz, hyperref}\n\
|
||||
\\DeclareMathOperator{\\rank}{rank}\n\
|
||||
\\setlength{\\parindent}{0pt}\n\
|
||||
\n\
|
||||
\\begin{document}\n\
|
||||
\\pagestyle{empty}\n\
|
||||
\\tableofcontents\n\
|
||||
\\sloppy\n");
|
||||
|
||||
compute_szabo_sseq (c).texshow (outfp, d.name);
|
||||
|
||||
fprintf (outfp, "\\end{document}\n");
|
||||
|
||||
if (file)
|
||||
fclose (outfp);
|
||||
}
|
666
kk.cpp
Normal file
666
kk.cpp
Normal file
@ -0,0 +1,666 @@
|
||||
|
||||
#include <knotkit.h>
|
||||
|
||||
const char *program_name;
|
||||
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
printf ("usage: %s <invariant> [options...] <link>\n", program_name);
|
||||
printf (" compute <invariant> for knot or link <link>\n");
|
||||
printf ("<invariant> can be one of:\n");
|
||||
printf (" kh: Khovanov homology\n");
|
||||
printf (" gss: Szabo's geometric spectral sequence\n");
|
||||
printf (" lsss: Batson-Seed link splitting spectral sequence\n");
|
||||
printf (" component weights are 0, 1, ..., m\n");
|
||||
printf (" sq2: Lipshitz-Sarkar Steenrod square on Z/2 Kh\n");
|
||||
printf (" output suitable for Sage\n");
|
||||
printf (" leess: spectral sequence coming from Bar-Natan analogue of Lee's\n");
|
||||
printf (" deformation of Khovanov's complex (whew!)\n");
|
||||
printf (" s: Rasmussen's s-invariant coming from lee\n");
|
||||
printf ("output:\n");
|
||||
printf (" kh, gss, lsss, leess: .tex file\n");
|
||||
printf (" sq2: text in Sage format\n");
|
||||
printf (" s: text\n");
|
||||
printf ("options:\n");
|
||||
printf (" -r : compute reduced theory\n");
|
||||
printf (" -h : print this message\n");
|
||||
printf (" -o <file> : write output to <file>\n");
|
||||
printf (" (stdout is the default)\n");
|
||||
printf (" -f <field> : ground field (if applicable)\n");
|
||||
printf (" (Z2 is the default)\n");
|
||||
printf (" -v : verbose: report progress as the computation proceeds\n");
|
||||
printf ("<field> can be one of:\n");
|
||||
printf (" Z2, Z3, Q\n");
|
||||
printf ("<link> can be one of:\n");
|
||||
printf (" - the unknot, e.g. U or unknot\n");
|
||||
printf (" - a torus knot, e.g. T(2,3)\n");
|
||||
printf (" - a Rolfsen table knot, e.g. 10_124\n");
|
||||
printf (" - a Hoste-Thistlethwaite-Weeks knot, e.g. 11a12 or 12n214\n");
|
||||
printf (" - a Morwen Thistlethwaite link, e.g. L8n9 or L13n8862\n");
|
||||
printf (" - a planar diagram, e.g.\n");
|
||||
printf (" PD[X[1, 4, 2, 5], X[3, 6, 4, 1], X[5, 2, 6, 3]] or\n");
|
||||
printf (" PD[[1, 4, 2, 5], [3, 6, 4, 1], [5, 2, 6, 3]]\n");
|
||||
printf (" - a Dowker-Thistlethwaite code, e.g.\n");
|
||||
printf (" DTCode[6,8,2,4],\n");
|
||||
printf (" DT[dadbcda] or\n");
|
||||
printf (" DT[{6, -8}, {-10, 12, -14, 2, -4}]\n");
|
||||
printf (" - a braid, e.g. BR[2, {-1, -1, -1}]\n");
|
||||
printf (" - disjoint union (juxtaposition), e.g. T(2,3) U\n");
|
||||
}
|
||||
|
||||
FILE *outfp = stdout;
|
||||
|
||||
void tex_header ()
|
||||
{
|
||||
fprintf (outfp, "\\documentclass{article}\n\
|
||||
\\usepackage{amsmath, tikz, hyperref}\n\
|
||||
\\DeclareMathOperator{\\rank}{rank}\n\
|
||||
\\setlength{\\parindent}{0pt}\n\
|
||||
\n\
|
||||
\\begin{document}\n\
|
||||
\\pagestyle{empty}\n\
|
||||
\\sloppy\n");
|
||||
}
|
||||
|
||||
void tex_footer ()
|
||||
{
|
||||
fprintf (outfp, "\\end{document}\n");
|
||||
}
|
||||
|
||||
const char *knot = 0;
|
||||
const char *invariant = 0;
|
||||
const char *field = "Z2";
|
||||
|
||||
knot_diagram kd;
|
||||
|
||||
bool reduced = 0;
|
||||
|
||||
class hg_grading_mapper
|
||||
{
|
||||
unsigned m;
|
||||
|
||||
public:
|
||||
hg_grading_mapper (unsigned m_) : m(m_) { }
|
||||
|
||||
grading operator () (grading hq) const
|
||||
{
|
||||
int t = hq.q - (int)m;
|
||||
if (reduced)
|
||||
t --;
|
||||
|
||||
assert (is_even (t));
|
||||
return grading (hq.h, t / 2);
|
||||
}
|
||||
|
||||
grading map_delta (grading d_hq) const
|
||||
{
|
||||
assert (is_even (d_hq.q));
|
||||
return grading (d_hq.h, d_hq.q / 2);
|
||||
}
|
||||
|
||||
void x_label (FILE *fp, int h) const
|
||||
{
|
||||
fprintf (fp, "%d", h);
|
||||
}
|
||||
void y_label (FILE *fp, int g) const
|
||||
{
|
||||
unsigned q = 2*g + (int)m;
|
||||
if (reduced)
|
||||
q ++;
|
||||
|
||||
fprintf (fp, "%d", q);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R> mod_map<R>
|
||||
compute_link_splitting_d (knot_diagram &kd,
|
||||
cube<R> &c,
|
||||
basedvector<R, 1> comp_weight)
|
||||
{
|
||||
unsigned n = kd.num_components ();
|
||||
|
||||
unionfind<1> u (kd.num_edges ());
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
{
|
||||
u.join (kd.ept_edge (kd.crossings[i][1]),
|
||||
kd.ept_edge (kd.crossings[i][3]));
|
||||
u.join (kd.ept_edge (kd.crossings[i][2]),
|
||||
kd.ept_edge (kd.crossings[i][4]));
|
||||
}
|
||||
|
||||
map<unsigned, unsigned> root_comp;
|
||||
unsigned t = 0;
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
{
|
||||
if (u.find (i) == i)
|
||||
{
|
||||
++ t;
|
||||
root_comp.push (i, t);
|
||||
}
|
||||
}
|
||||
assert (t == n);
|
||||
|
||||
assert (comp_weight.size () == n);
|
||||
|
||||
map<unsigned, R> crossing_over_sign;
|
||||
|
||||
// crossings
|
||||
set<unsigned> pending;
|
||||
set<unsigned> finished;
|
||||
|
||||
crossing_over_sign.push (1, R (1));
|
||||
pending.push (1);
|
||||
|
||||
while (pending.card () > 0)
|
||||
{
|
||||
unsigned x = pending.pop ();
|
||||
finished.push (x);
|
||||
|
||||
R s = crossing_over_sign(x);
|
||||
|
||||
for (unsigned j = 1; j <= 4; j ++)
|
||||
{
|
||||
unsigned p = kd.crossings[x][j];
|
||||
R t = kd.is_over_ept (p) ? s : -s; // sign of (x, p)
|
||||
|
||||
unsigned q = kd.edge_other_ept (p);
|
||||
unsigned x2 = kd.ept_crossing[q];
|
||||
|
||||
R u = kd.is_over_ept (q) ? -t : t;
|
||||
|
||||
if (crossing_over_sign % x2)
|
||||
assert (crossing_over_sign(x2) == u);
|
||||
else
|
||||
crossing_over_sign.push (x2, u);
|
||||
|
||||
if (! (finished % x2))
|
||||
pending += x2;
|
||||
}
|
||||
}
|
||||
assert (finished.card () == kd.n_crossings);
|
||||
|
||||
mod_map<R> untwisted_d = c.compute_d (1, 0, 0, 0, 0);
|
||||
assert (untwisted_d.compose (untwisted_d) == 0);
|
||||
|
||||
mod_map<R> d = untwisted_d;
|
||||
for (unsigned x = 1; x <= kd.n_crossings; x ++)
|
||||
{
|
||||
unsigned p1 = kd.crossings[x][1],
|
||||
p2 = kd.crossings[x][2];
|
||||
assert (kd.is_over_ept (p2));
|
||||
|
||||
unsigned r1 = u.find (kd.ept_edge (p1)),
|
||||
r2 = u.find (kd.ept_edge (p2));
|
||||
|
||||
unsigned c1 = root_comp(r1),
|
||||
c2 = root_comp(r2);
|
||||
|
||||
if (c1 != c2)
|
||||
{
|
||||
R s = crossing_over_sign(x);
|
||||
|
||||
R w_under = comp_weight[c1];
|
||||
R w_over = comp_weight[c2];
|
||||
|
||||
d = d + c.compute_dinv (x)*(s*(w_over - w_under));
|
||||
}
|
||||
}
|
||||
|
||||
assert (d.compose (d) == 0);
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
compute_gss ()
|
||||
{
|
||||
cube<Z2> c (kd, reduced);
|
||||
ptr<const module<Z2> > C = c.khC;
|
||||
mod_map<Z2> d = c.compute_d (0, 0, 0, 0, 0);
|
||||
|
||||
unsigned m = kd.num_components ();
|
||||
hg_grading_mapper mapper (m);
|
||||
|
||||
sseq_bounds b (C, mapper);
|
||||
basedvector<sseq_page, 1> pages;
|
||||
|
||||
unsigned k = 1;
|
||||
for (;;)
|
||||
{
|
||||
chain_complex_simplifier<Z2> s (C, d,
|
||||
maybe<int> (k), maybe<int> (2*k - 2));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
k ++;
|
||||
|
||||
grading dk_gr (k, 2*k - 2);
|
||||
pages.append (sseq_page (b, k, dk_gr, d.graded_piece (dk_gr), mapper));
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
sseq ss (b, pages);
|
||||
|
||||
tex_header ();
|
||||
fprintf (outfp, "$E_k = %s^{Sz}_k(\\verb~%s~; \\verb~%s~)$:\\\\\n",
|
||||
(reduced
|
||||
? "\\widetilde{E}"
|
||||
: "E"),
|
||||
knot, field);
|
||||
ss.texshow (outfp, mapper);
|
||||
tex_footer ();
|
||||
}
|
||||
|
||||
template<class R> void
|
||||
compute_invariant ()
|
||||
{
|
||||
if (!strcmp (invariant, "kh"))
|
||||
{
|
||||
cube<R> c (kd, reduced);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
mod_map<R> d = c.compute_d (1, 0, 0, 0, 0);
|
||||
|
||||
unsigned m = kd.num_components ();
|
||||
hg_grading_mapper mapper (m);
|
||||
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1), maybe<int> (0));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
|
||||
sseq_bounds b (C, mapper);
|
||||
sseq_page pg (b, 2, grading (0, 0), mod_map<R> (C), mapper);
|
||||
|
||||
tex_header ();
|
||||
|
||||
fprintf (outfp, "Kh = $%s(\\verb~%s~; \\verb~%s~)$:\\\\\n",
|
||||
(reduced
|
||||
? "\\widetilde{Kh}"
|
||||
: "Kh"),
|
||||
knot,
|
||||
field);
|
||||
fprintf (outfp, "$\\rank Kh = %d$\\\\\n", C->dim ());
|
||||
|
||||
char buf[1000];
|
||||
sprintf (buf, "$Kh$");
|
||||
pg.texshow (outfp, b, buf, mapper);
|
||||
|
||||
tex_footer ();
|
||||
}
|
||||
else if (!strcmp (invariant, "lsss"))
|
||||
{
|
||||
cube<R> c (kd, reduced);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
|
||||
unsigned m = kd.num_components ();
|
||||
basedvector<R, 1> comp_weight (m);
|
||||
for (unsigned i = 1; i <= m; i ++)
|
||||
comp_weight[i] = R ((int)(i - 1));
|
||||
|
||||
mod_map<R> d = compute_link_splitting_d (kd, c, comp_weight);
|
||||
|
||||
hg_grading_mapper mapper (m);
|
||||
|
||||
sseq_bounds b (C, mapper);
|
||||
basedvector<sseq_page, 1> pages;
|
||||
|
||||
int k = 0;
|
||||
for (;;)
|
||||
{
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1 - 2*k), maybe<int> (-2*k));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
k ++;
|
||||
|
||||
grading dk_gr (1 - 2*k, -2*k);
|
||||
pages.append (sseq_page (b, k, dk_gr, d.graded_piece (dk_gr), mapper));
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
sseq ss (b, pages);
|
||||
|
||||
tex_header ();
|
||||
fprintf (outfp, "$E_k = %s^{BS}_k({}^{%d}\\verb~%s~; \\verb~%s~)$:\\\\\n",
|
||||
(reduced
|
||||
? "\\widetilde{E}"
|
||||
: "E"),
|
||||
m,
|
||||
knot,
|
||||
field);
|
||||
ss.texshow (outfp, mapper);
|
||||
tex_footer ();
|
||||
}
|
||||
else if (!strcmp (invariant, "leess"))
|
||||
{
|
||||
cube<R> c (kd, reduced);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
|
||||
mod_map<R> d = c.compute_d (1, 0, 0, 0, 0);
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
d = d + c.H_i (i);
|
||||
assert (d.compose (d) == 0);
|
||||
|
||||
unsigned m = kd.num_components ();
|
||||
hg_grading_mapper mapper (m);
|
||||
|
||||
sseq_bounds b (C, mapper);
|
||||
basedvector<sseq_page, 1> pages;
|
||||
|
||||
int k = 0;
|
||||
for (;;)
|
||||
{
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1), maybe<int> (2*k));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
k ++;
|
||||
|
||||
grading dk_gr (1, 2*k);
|
||||
pages.append (sseq_page (b, k, dk_gr, d.graded_piece (dk_gr), mapper));
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
sseq ss (b, pages);
|
||||
|
||||
tex_header ();
|
||||
fprintf (outfp, "$E_k = %s^{BN}_k(\\verb~%s~; \\verb~%s~)$:\\\\\n",
|
||||
(reduced
|
||||
? "\\widetilde{E}"
|
||||
: "E"),
|
||||
knot, field);
|
||||
ss.texshow (outfp, mapper);
|
||||
tex_footer ();
|
||||
}
|
||||
else if (!strcmp (invariant, "s"))
|
||||
{
|
||||
unsigned m = kd.num_components ();
|
||||
if (m != 1)
|
||||
{
|
||||
fprintf (stderr, "error: s-invariant only defined for knots\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cube<R> c (kd, 0);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
|
||||
mod_map<R> d = c.compute_d (1, 0, 0, 0, 0);
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
d = d + c.H_i (i);
|
||||
assert (d.compose (d) == 0);
|
||||
|
||||
int k = 0;
|
||||
for (;;)
|
||||
{
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1), maybe<int> (2*k));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
k ++;
|
||||
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
assert (C->dim () == 2);
|
||||
grading gr1 = C->generator_grading (1),
|
||||
gr2 = C->generator_grading (2);
|
||||
|
||||
int qmin = gr1.q,
|
||||
qmax = gr2.q;
|
||||
if (qmax < qmin)
|
||||
std::swap (qmin, qmax);
|
||||
|
||||
assert (qmax == qmin + 2);
|
||||
|
||||
fprintf (outfp, "s(%s; %s) = %d\n", knot, field, qmin + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: unknown invariant %s\n", invariant);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sage_show (FILE *fp,
|
||||
map<grading, basedvector<unsigned, 1> > hq_gens,
|
||||
ptr<const module<Z2> > H)
|
||||
{
|
||||
fprintf (fp, "hom={");
|
||||
bool first = 1;
|
||||
for (map<grading, basedvector<unsigned, 1> >::const_iter i = hq_gens; i; i ++)
|
||||
{
|
||||
if (first)
|
||||
first = 0;
|
||||
else
|
||||
fprintf (fp, ", ");
|
||||
fprintf (fp, "(%d, %d): %d", i.key ().h, i.key ().q, i.val ().size ());
|
||||
}
|
||||
fprintf (fp, "}\n");
|
||||
}
|
||||
|
||||
void
|
||||
sage_show (FILE *fp,
|
||||
map<grading, basedvector<unsigned, 1> > hq_gens,
|
||||
std::string name,
|
||||
grading delta,
|
||||
mod_map<Z2> f)
|
||||
{
|
||||
fprintf (fp, "%s={", name.c_str ());
|
||||
|
||||
bool first = 1;
|
||||
for (map<grading, basedvector<unsigned, 1> >::const_iter i = hq_gens; i; i ++)
|
||||
{
|
||||
grading from_hq = i.key ();
|
||||
basedvector<unsigned, 1> from_gens = i.val ();
|
||||
|
||||
grading to_hq = from_hq + delta;
|
||||
if (hq_gens % to_hq)
|
||||
{
|
||||
basedvector<unsigned, 1> to_gens = hq_gens(to_hq);
|
||||
|
||||
if (first)
|
||||
first = 0;
|
||||
else
|
||||
fprintf (fp, ", ");
|
||||
fprintf (fp, "(%d, %d): [", from_hq.h, from_hq.q);
|
||||
bool first2 = 1;
|
||||
for (unsigned j = 1; j <= from_gens.size (); j ++)
|
||||
{
|
||||
unsigned gj = from_gens[j];
|
||||
|
||||
if (first2)
|
||||
first2 = 0;
|
||||
else
|
||||
fprintf (fp, ", ");
|
||||
fprintf (fp, "(");
|
||||
for (unsigned k = 1; k <= to_gens.size (); k ++)
|
||||
{
|
||||
unsigned gk = to_gens[k];
|
||||
|
||||
if (k > 1)
|
||||
fprintf (fp, ", ");
|
||||
if (f[gj](gk) == 1)
|
||||
fprintf (fp, "1");
|
||||
else
|
||||
{
|
||||
assert (f[gj](gk) == 0);
|
||||
fprintf (fp, "0");
|
||||
}
|
||||
}
|
||||
fprintf (fp, ")");
|
||||
}
|
||||
fprintf (fp, "]");
|
||||
}
|
||||
}
|
||||
fprintf (fp, "}\n");
|
||||
}
|
||||
|
||||
void
|
||||
sage_show_khsq (FILE *fp,
|
||||
ptr<const module<Z2> > H,
|
||||
mod_map<Z2> sq1,
|
||||
mod_map<Z2> sq2)
|
||||
{
|
||||
unsigned n = H->dim ();
|
||||
|
||||
map<grading, basedvector<unsigned, 1> > hq_gens;
|
||||
for (unsigned i = 1; i <= H->dim (); i ++)
|
||||
hq_gens[H->generator_grading (i)].append (i);
|
||||
|
||||
unsigned t = 0;
|
||||
for (map<grading, basedvector<unsigned, 1> >::const_iter i = hq_gens; i; i ++)
|
||||
t += i.val ().size ();
|
||||
assert (t == n);
|
||||
|
||||
sage_show (fp, hq_gens, H);
|
||||
sage_show (fp, hq_gens, "sq1", grading (1, 0), sq1);
|
||||
sage_show (fp, hq_gens, "sq2", grading (2, 0), sq2);
|
||||
}
|
||||
|
||||
void
|
||||
compute_sq2 ()
|
||||
{
|
||||
cube<Z2> c (kd);
|
||||
mod_map<Z2> d = c.compute_d (1, 0, 0, 0, 0);
|
||||
|
||||
chain_complex_simplifier<Z2> s (c.khC, d, maybe<int> (1), maybe<int> (0));
|
||||
assert (s.new_d == 0);
|
||||
|
||||
steenrod_square sq (c, d, s);
|
||||
mod_map<Z2> sq1 = sq.sq1 ();
|
||||
mod_map<Z2> sq2 = sq.sq2 ();
|
||||
|
||||
ptr<const module<Z2> > H = sq1.domain ();
|
||||
|
||||
sage_show_khsq (outfp, H, sq1, sq2);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
program_name = argv[0];
|
||||
|
||||
const char *file = 0;
|
||||
|
||||
for (int i = 1; i < argc; i ++)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
if (strcmp (argv[i], "-r") == 0)
|
||||
reduced = 1;
|
||||
else if (strcmp (argv[i], "-h") == 0)
|
||||
{
|
||||
usage ();
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
else if (!strcmp (argv[i], "-v"))
|
||||
verbose = 1;
|
||||
else if (!strcmp (argv[i], "-f"))
|
||||
{
|
||||
i ++;
|
||||
if (i == argc)
|
||||
{
|
||||
fprintf (stderr, "error: missing argument to option `-f'\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
field = argv[i];
|
||||
}
|
||||
else if (!strcmp (argv[i], "-o"))
|
||||
{
|
||||
i ++;
|
||||
if (i == argc)
|
||||
{
|
||||
fprintf (stderr, "error: missing argument to option `-o'\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
file = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: unknown argument `%s'\n", argv[1]);
|
||||
fprintf (stderr, " use -h for usage\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (knot)
|
||||
{
|
||||
fprintf (stderr, "error: too many arguments\n");
|
||||
fprintf (stderr, " use -h for usage\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
else if (invariant)
|
||||
knot = argv[i];
|
||||
else
|
||||
{
|
||||
assert (invariant == 0);
|
||||
invariant = argv[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!knot)
|
||||
{
|
||||
fprintf (stderr, "error: too few arguments, <invariant> or <knot> missing\n");
|
||||
fprintf (stderr, " use -h for usage\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (file)
|
||||
{
|
||||
outfp = fopen (file, "w");
|
||||
if (!outfp)
|
||||
{
|
||||
stderror ("fopen: %s", file);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
outfp = stdout;
|
||||
|
||||
kd = parse_knot (knot);
|
||||
kd.marked_edge = 1;
|
||||
|
||||
if (!strcmp (invariant, "sq2"))
|
||||
{
|
||||
if (strcmp (field, "Z2"))
|
||||
{
|
||||
fprintf (stderr, "warning: sq2 only defined over Z2, ignoring -f %s\n", field);
|
||||
field = "Z2";
|
||||
}
|
||||
|
||||
compute_sq2 ();
|
||||
}
|
||||
else if (!strcmp (invariant, "gss"))
|
||||
{
|
||||
if (strcmp (field, "Z2"))
|
||||
{
|
||||
fprintf (stderr, "warning: gss only defined over Z2, ignoring -f %s\n", field);
|
||||
field = "Z2";
|
||||
}
|
||||
|
||||
compute_gss ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp (field, "Z2"))
|
||||
compute_invariant<Z2> ();
|
||||
else if (!strcmp (field, "Z3"))
|
||||
compute_invariant<Zp<3> > ();
|
||||
else if (!strcmp (field, "Q"))
|
||||
compute_invariant<Q> ();
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: unknown field %s\n", field);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (file)
|
||||
fclose (outfp);
|
||||
}
|
117
knot_diagram.cpp
117
knot_diagram.cpp
@ -22,7 +22,7 @@ knot_diagram::knot_diagram (const planar_diagram &pd)
|
||||
crossings[c] = basedvector<unsigned, 1> (4);
|
||||
}
|
||||
|
||||
smallbitset done (num_edges ());
|
||||
set<unsigned> done;
|
||||
for (unsigned c0 = 1; c0 <= n_crossings; c0 ++)
|
||||
{
|
||||
for (unsigned i0 = 1; i0 <= 2; i0 ++)
|
||||
@ -82,10 +82,10 @@ public:
|
||||
|
||||
public:
|
||||
dt_layout (const dt_code &dt, knot_diagram &kd_);
|
||||
dt_layout (const dt_layout &); // doesn't exist
|
||||
dt_layout (const dt_layout &) = delete;
|
||||
~dt_layout () { }
|
||||
|
||||
dt_layout &operator = (const dt_layout &); // doesn't exist
|
||||
dt_layout &operator = (const dt_layout &) = delete;
|
||||
|
||||
unsigned find_crossing (unsigned prevc, unsigned previ, unsigned target,
|
||||
bool under, unsigned dir);
|
||||
@ -454,6 +454,60 @@ knot_diagram::knot_diagram (sublink,
|
||||
calculate_nminus_nplus ();
|
||||
}
|
||||
|
||||
knot_diagram::knot_diagram (disjoint_union,
|
||||
const knot_diagram &kd1,
|
||||
const knot_diagram &kd2)
|
||||
: name(kd1.name + "+" + kd2.name),
|
||||
n_crossings(kd1.n_crossings + kd2.n_crossings),
|
||||
marked_edge(0),
|
||||
crossings(n_crossings),
|
||||
nminus(kd1.nminus + kd2.nminus),
|
||||
nplus(kd1.nplus + kd2.nplus)
|
||||
{
|
||||
assert (kd1.marked_edge == 0);
|
||||
assert (kd2.marked_edge == 0);
|
||||
|
||||
for (unsigned i = 1; i <= n_crossings; i ++)
|
||||
crossings[i] = basedvector<unsigned, 1> (4);
|
||||
|
||||
for (unsigned i = 1; i <= kd1.n_crossings; i ++)
|
||||
for (unsigned j = 1; j <= 4; j ++)
|
||||
crossings[i][j] = kd1.crossings[i][j];
|
||||
|
||||
for (unsigned e = 1; e <= kd1.num_edges (); e ++)
|
||||
{
|
||||
if (kd1.edge_smoothing_oriented % e)
|
||||
edge_smoothing_oriented.push (e);
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i <= kd2.n_crossings; i ++)
|
||||
for (unsigned j = 1; j <= 4; j ++)
|
||||
crossings[kd1.n_crossings + i][j] = kd1.num_epts () + kd2.crossings[i][j];
|
||||
|
||||
for (unsigned e = 1; e <= kd2.num_edges (); e ++)
|
||||
{
|
||||
if (kd2.edge_smoothing_oriented % e)
|
||||
edge_smoothing_oriented.push (kd1.num_edges () + e);
|
||||
}
|
||||
|
||||
// ?? break this out into aux function
|
||||
ept_crossing = basedvector<unsigned, 1> (num_epts ());
|
||||
ept_index = basedvector<unsigned, 1> (num_epts ());
|
||||
for (unsigned i = 1; i <= n_crossings; i ++)
|
||||
{
|
||||
for (unsigned j = 1; j <= 4; j ++)
|
||||
{
|
||||
unsigned p = crossings[i][j];
|
||||
ept_crossing[p] = i;
|
||||
ept_index[p] = j;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
check_crossings ();
|
||||
#endif
|
||||
}
|
||||
|
||||
knot_diagram::knot_diagram (mirror, const knot_diagram &kd)
|
||||
: name("mirror(" + kd.name + ")"),
|
||||
n_crossings(kd.n_crossings),
|
||||
@ -521,6 +575,63 @@ knot_diagram::rotate_crossing (unsigned c)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
knot_diagram::total_linking_number () const
|
||||
{
|
||||
unionfind<1> u (num_edges ());
|
||||
|
||||
for (unsigned i = 1; i <= n_crossings; i ++)
|
||||
{
|
||||
u.join (ept_edge (crossings[i][1]),
|
||||
ept_edge (crossings[i][3]));
|
||||
u.join (ept_edge (crossings[i][2]),
|
||||
ept_edge (crossings[i][4]));
|
||||
}
|
||||
unsigned n = u.num_sets ();
|
||||
|
||||
map<unsigned, unsigned> root_comp;
|
||||
unsigned t = 0;
|
||||
for (unsigned i = 1; i <= num_edges (); i ++)
|
||||
{
|
||||
if (u.find (i) == i)
|
||||
{
|
||||
++ t;
|
||||
root_comp.push (i, t);
|
||||
}
|
||||
}
|
||||
assert (t == n);
|
||||
|
||||
unsigned total_lk = 0;
|
||||
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
for (unsigned j = i + 1; j <= n; j ++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
int lk = 0;
|
||||
for (unsigned x = 1; x <= n_crossings; x ++)
|
||||
{
|
||||
unsigned r1 = root_comp(u.find (ept_edge (crossings[x][1]))),
|
||||
r2 = root_comp(u.find (ept_edge (crossings[x][2])));
|
||||
if (((r1 == i) && (r2 == j))
|
||||
|| ((r2 == i) && (r1 == j)))
|
||||
{
|
||||
if (is_to_ept (crossings[x][1]) == is_to_ept (crossings[x][4]))
|
||||
lk ++;
|
||||
else
|
||||
lk --;
|
||||
}
|
||||
}
|
||||
assert (is_even (lk));
|
||||
lk /= 2;
|
||||
|
||||
total_lk += abs (lk);
|
||||
}
|
||||
|
||||
return total_lk;
|
||||
}
|
||||
|
||||
knot_diagram::knot_diagram (connect_sum,
|
||||
const knot_diagram &d1,
|
||||
const knot_diagram &d2)
|
||||
|
@ -1,4 +1,14 @@
|
||||
|
||||
// for building knot_diagram
|
||||
inline unsigned edge_from_ept (unsigned e)
|
||||
{
|
||||
return e * 2 - 1;
|
||||
}
|
||||
inline unsigned edge_to_ept (unsigned e)
|
||||
{
|
||||
return e * 2;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
add_base1_mod4 (unsigned x, unsigned y)
|
||||
{
|
||||
@ -11,6 +21,7 @@ add_base1_mod4 (unsigned x, unsigned y)
|
||||
enum mirror { MIRROR };
|
||||
enum connect_sum { CONNECT_SUM };
|
||||
enum sublink { SUBLINK };
|
||||
enum disjoint_union { DISJOINT_UNION };
|
||||
|
||||
class knot_diagram
|
||||
{
|
||||
@ -122,6 +133,9 @@ class knot_diagram
|
||||
knot_diagram (sublink,
|
||||
smallbitset c,
|
||||
const knot_diagram &kd);
|
||||
knot_diagram (disjoint_union,
|
||||
const knot_diagram &kd1,
|
||||
const knot_diagram &kd2);
|
||||
|
||||
knot_diagram (const std::string &name_, unsigned n_crossings_, unsigned crossings_ar[][4]);
|
||||
knot_diagram (const std::string &name_, const basedvector<basedvector<unsigned, 1>, 1> &crossings_);
|
||||
@ -157,6 +171,8 @@ class knot_diagram
|
||||
|
||||
int writhe () const { return (int)nplus - (int)nminus; }
|
||||
|
||||
unsigned total_linking_number () const;
|
||||
|
||||
basedvector<basedvector<int, 1>, 1> planar_diagram_crossings () const;
|
||||
|
||||
hash_t hash_self () const;
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.3. */
|
||||
/* A Bison parser, made by GNU Bison 2.6.5. */
|
||||
|
||||
/* Skeleton implementation for Bison LALR(1) parsers in C++
|
||||
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -34,37 +33,41 @@
|
||||
|
||||
/* First part of user declarations. */
|
||||
|
||||
|
||||
/* Line 311 of lalr1.cc */
|
||||
#line 40 "knot_parser/knot_parser.cc"
|
||||
/* Line 278 of lalr1.cc */
|
||||
#line 38 "knot_parser/knot_parser.cc"
|
||||
|
||||
|
||||
#include "knot_parser.hh"
|
||||
|
||||
/* User implementation prologue. */
|
||||
|
||||
|
||||
/* Line 317 of lalr1.cc */
|
||||
#line 49 "knot_parser/knot_parser.cc"
|
||||
/* Line 284 of lalr1.cc */
|
||||
#line 46 "knot_parser/knot_parser.cc"
|
||||
/* Unqualified %code blocks. */
|
||||
|
||||
/* Line 318 of lalr1.cc */
|
||||
/* Line 285 of lalr1.cc */
|
||||
#line 15 "knot_parser/knot_parser.yy"
|
||||
|
||||
#define YY_DECL \
|
||||
yy::knot_parser::token_type knot_yylex (yy::knot_parser::semantic_type *yylval)
|
||||
YY_DECL;
|
||||
|
||||
|
||||
/* Line 318 of lalr1.cc */
|
||||
#line 29 "knot_parser/knot_parser.yy"
|
||||
/* Line 285 of lalr1.cc */
|
||||
#line 30 "knot_parser/knot_parser.yy"
|
||||
|
||||
#define yylex knot_yylex
|
||||
|
||||
|
||||
/* Line 285 of lalr1.cc */
|
||||
#line 62 "knot_parser/knot_parser.cc"
|
||||
|
||||
/* Line 318 of lalr1.cc */
|
||||
#line 68 "knot_parser/knot_parser.cc"
|
||||
|
||||
# ifndef YY_NULL
|
||||
# if defined __cplusplus && 201103L <= __cplusplus
|
||||
# define YY_NULL nullptr
|
||||
# else
|
||||
# define YY_NULL 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#ifndef YY_
|
||||
# if defined YYENABLE_NLS && YYENABLE_NLS
|
||||
@ -78,6 +81,27 @@ YY_DECL;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define YYRHSLOC(Rhs, K) ((Rhs)[K])
|
||||
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
|
||||
If N is 0, then set CURRENT to the empty location which ends
|
||||
the previous symbol: RHS[0] (always defined). */
|
||||
|
||||
# ifndef YYLLOC_DEFAULT
|
||||
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
||||
do \
|
||||
if (N) \
|
||||
{ \
|
||||
(Current).begin = YYRHSLOC (Rhs, 1).begin; \
|
||||
(Current).end = YYRHSLOC (Rhs, N).end; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \
|
||||
} \
|
||||
while (/*CONSTCOND*/ false)
|
||||
# endif
|
||||
|
||||
|
||||
/* Suppress unused-variable warnings by "using" E. */
|
||||
#define YYUSE(e) ((void) (e))
|
||||
|
||||
@ -128,49 +152,8 @@ do { \
|
||||
|
||||
|
||||
namespace yy {
|
||||
|
||||
/* Line 380 of lalr1.cc */
|
||||
#line 134 "knot_parser/knot_parser.cc"
|
||||
#if YYERROR_VERBOSE
|
||||
|
||||
/* Return YYSTR after stripping away unnecessary quotes and
|
||||
backslashes, so that it's suitable for yyerror. The heuristic is
|
||||
that double-quoting is unnecessary unless the string contains an
|
||||
apostrophe, a comma, or backslash (other than backslash-backslash).
|
||||
YYSTR is taken from yytname. */
|
||||
std::string
|
||||
knot_parser::yytnamerr_ (const char *yystr)
|
||||
{
|
||||
if (*yystr == '"')
|
||||
{
|
||||
std::string yyr = "";
|
||||
char const *yyp = yystr;
|
||||
|
||||
for (;;)
|
||||
switch (*++yyp)
|
||||
{
|
||||
case '\'':
|
||||
case ',':
|
||||
goto do_not_strip_quotes;
|
||||
|
||||
case '\\':
|
||||
if (*++yyp != '\\')
|
||||
goto do_not_strip_quotes;
|
||||
/* Fall through. */
|
||||
default:
|
||||
yyr += *yyp;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
return yyr;
|
||||
}
|
||||
do_not_strip_quotes: ;
|
||||
}
|
||||
|
||||
return yystr;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Line 352 of lalr1.cc */
|
||||
#line 157 "knot_parser/knot_parser.cc"
|
||||
|
||||
/// Build a parser object.
|
||||
knot_parser::knot_parser (knot_diagram &parsed_knot_yyarg)
|
||||
@ -198,6 +181,9 @@ namespace yy {
|
||||
{
|
||||
YYUSE (yylocationp);
|
||||
YYUSE (yyvaluep);
|
||||
std::ostream& yyo = debug_stream ();
|
||||
std::ostream& yyoutput = yyo;
|
||||
YYUSE (yyoutput);
|
||||
switch (yytype)
|
||||
{
|
||||
default:
|
||||
@ -271,6 +257,18 @@ namespace yy {
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
knot_parser::yy_pact_value_is_default_ (int yyvalue)
|
||||
{
|
||||
return yyvalue == yypact_ninf_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
knot_parser::yy_table_value_is_error_ (int yyvalue)
|
||||
{
|
||||
return yyvalue == yytable_ninf_;
|
||||
}
|
||||
|
||||
int
|
||||
knot_parser::parse ()
|
||||
{
|
||||
@ -278,17 +276,18 @@ namespace yy {
|
||||
int yychar = yyempty_;
|
||||
int yytoken = 0;
|
||||
|
||||
/* State. */
|
||||
// State.
|
||||
int yyn;
|
||||
int yylen = 0;
|
||||
int yystate = 0;
|
||||
|
||||
/* Error handling. */
|
||||
// Error handling.
|
||||
int yynerrs_ = 0;
|
||||
int yyerrstatus_ = 0;
|
||||
|
||||
/// Semantic value of the lookahead.
|
||||
semantic_type yylval;
|
||||
static semantic_type yyval_default;
|
||||
semantic_type yylval = yyval_default;
|
||||
/// Location of the lookahead.
|
||||
location_type yylloc;
|
||||
/// The locations where the error started and ended.
|
||||
@ -330,7 +329,7 @@ namespace yy {
|
||||
|
||||
/* Try to take a decision without lookahead. */
|
||||
yyn = yypact_[yystate];
|
||||
if (yyn == yypact_ninf_)
|
||||
if (yy_pact_value_is_default_ (yyn))
|
||||
goto yydefault;
|
||||
|
||||
/* Read a lookahead token. */
|
||||
@ -340,7 +339,6 @@ namespace yy {
|
||||
yychar = yylex (&yylval);
|
||||
}
|
||||
|
||||
|
||||
/* Convert token to internal form. */
|
||||
if (yychar <= yyeof_)
|
||||
{
|
||||
@ -363,8 +361,8 @@ namespace yy {
|
||||
yyn = yytable_[yyn];
|
||||
if (yyn <= 0)
|
||||
{
|
||||
if (yyn == 0 || yyn == yytable_ninf_)
|
||||
goto yyerrlab;
|
||||
if (yy_table_value_is_error_ (yyn))
|
||||
goto yyerrlab;
|
||||
yyn = -yyn;
|
||||
goto yyreduce;
|
||||
}
|
||||
@ -418,17 +416,35 @@ namespace yy {
|
||||
YY_REDUCE_PRINT (yyn);
|
||||
switch (yyn)
|
||||
{
|
||||
case 10:
|
||||
case 2:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 60 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
parsed_knot = *(yysemantic_stack_[(1) - (1)].kd);
|
||||
delete (yysemantic_stack_[(1) - (1)].kd);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 67 "knot_parser/knot_parser.yy"
|
||||
case 4:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 69 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
(yyval.kd) = new knot_diagram (DISJOINT_UNION, *(yysemantic_stack_[(2) - (1)].kd), *(yysemantic_stack_[(2) - (2)].kd));
|
||||
delete (yysemantic_stack_[(2) - (1)].kd);
|
||||
delete (yysemantic_stack_[(2) - (2)].kd);
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 89 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
unsigned n = (yysemantic_stack_[(3) - (1)].integer),
|
||||
k = (yysemantic_stack_[(3) - (3)].integer);
|
||||
|
||||
if (n >= 1 && n <= 10
|
||||
&& k >= 1 && k <= rolfsen_crossing_knots (n))
|
||||
parsed_knot = knot_diagram (rolfsen_knot (n, k));
|
||||
(yyval.kd) = new knot_diagram (rolfsen_knot (n, k));
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "knot_parser: no such Rolfsen knot `%d_%d'\n",
|
||||
@ -438,10 +454,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 11:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 85 "knot_parser/knot_parser.yy"
|
||||
case 14:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 107 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
unsigned n = (yysemantic_stack_[(3) - (1)].integer),
|
||||
k = (yysemantic_stack_[(3) - (3)].integer);
|
||||
@ -449,7 +464,7 @@ namespace yy {
|
||||
|
||||
if (n >= 1 && n <= 16
|
||||
&& k >= 1 && k <= htw_knots (n, alt))
|
||||
parsed_knot = knot_diagram (htw_knot (n, alt, k));
|
||||
(yyval.kd) = new knot_diagram (htw_knot (n, alt, k));
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "knot_parser: no such HTW knot `%d%c%d'\n",
|
||||
@ -459,10 +474,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 104 "knot_parser/knot_parser.yy"
|
||||
case 15:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 126 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
unsigned n = (yysemantic_stack_[(4) - (2)].integer),
|
||||
k = (yysemantic_stack_[(4) - (4)].integer);
|
||||
@ -470,7 +484,7 @@ namespace yy {
|
||||
|
||||
if (n >= 1 && n <= 14
|
||||
&& k >= 1 && k <= mt_links (n, alt))
|
||||
parsed_knot = knot_diagram (mt_link (n, alt, k));
|
||||
(yyval.kd) = new knot_diagram (mt_link (n, alt, k));
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "knot_parser: no such MT link `%d%c%d'\n",
|
||||
@ -480,75 +494,66 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 123 "knot_parser/knot_parser.yy"
|
||||
{ parsed_knot = knot_diagram (planar_diagram ("<parsed>", *(yysemantic_stack_[(4) - (3)].int_vec2))); }
|
||||
break;
|
||||
|
||||
case 14:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 125 "knot_parser/knot_parser.yy"
|
||||
{ parsed_knot = knot_diagram (planar_diagram ("<parsed>", *(yysemantic_stack_[(4) - (3)].int_vec2))); }
|
||||
break;
|
||||
|
||||
case 15:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 130 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> even_labels (1);
|
||||
even_labels[1] = *(yysemantic_stack_[(4) - (3)].int_vec);
|
||||
parsed_knot = knot_diagram (dt_code ("<parsed>", even_labels));
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 136 "knot_parser/knot_parser.yy"
|
||||
{ parsed_knot = knot_diagram (dt_code ("<parsed>", *(yysemantic_stack_[(4) - (3)].int_vec2))); }
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 145 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.kd) = new knot_diagram (planar_diagram ("<parsed>", *(yysemantic_stack_[(4) - (3)].int_vec2))); }
|
||||
break;
|
||||
|
||||
case 17:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 138 "knot_parser/knot_parser.yy"
|
||||
{ parsed_knot = knot_diagram (dt_code ("<parsed>", (yysemantic_stack_[(4) - (3)].string))); }
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 147 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.kd) = new knot_diagram (planar_diagram ("<parsed>", *(yysemantic_stack_[(4) - (3)].int_vec2))); }
|
||||
break;
|
||||
|
||||
case 18:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 143 "knot_parser/knot_parser.yy"
|
||||
{ parsed_knot = knot_diagram (torus_knot ((yysemantic_stack_[(6) - (3)].integer), (yysemantic_stack_[(6) - (5)].integer))); }
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 152 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> even_labels (1);
|
||||
even_labels[1] = *(yysemantic_stack_[(4) - (3)].int_vec);
|
||||
(yyval.kd) = new knot_diagram (dt_code ("<parsed>", even_labels));
|
||||
}
|
||||
break;
|
||||
|
||||
case 19:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 148 "knot_parser/knot_parser.yy"
|
||||
{ parsed_knot = knot_diagram (braid ((yysemantic_stack_[(6) - (3)].integer), *(yysemantic_stack_[(6) - (5)].int_vec))); }
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 158 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.kd) = new knot_diagram (dt_code ("<parsed>", *(yysemantic_stack_[(4) - (3)].int_vec2))); }
|
||||
break;
|
||||
|
||||
case 20:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 160 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.kd) = new knot_diagram (dt_code ("<parsed>", (yysemantic_stack_[(4) - (3)].string))); }
|
||||
break;
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 153 "knot_parser/knot_parser.yy"
|
||||
case 21:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 165 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.kd) = new knot_diagram (torus_knot ((yysemantic_stack_[(6) - (3)].integer), (yysemantic_stack_[(6) - (5)].integer))); }
|
||||
break;
|
||||
|
||||
case 22:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 170 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.kd) = new knot_diagram (braid ((yysemantic_stack_[(6) - (3)].integer), *(yysemantic_stack_[(6) - (5)].int_vec))); }
|
||||
break;
|
||||
|
||||
case 23:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 175 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
unsigned unknot_ar[1][4] = {
|
||||
{ 2, 1, 3, 4, },
|
||||
};
|
||||
parsed_knot = knot_diagram ("U", 1, unknot_ar);
|
||||
(yyval.kd) = new knot_diagram ("U", 1, unknot_ar);
|
||||
}
|
||||
break;
|
||||
|
||||
case 23:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 168 "knot_parser/knot_parser.yy"
|
||||
case 26:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 190 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> *v
|
||||
= new basedvector<basedvector<int, 1>, 1> ();
|
||||
@ -557,10 +562,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 24:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 175 "knot_parser/knot_parser.yy"
|
||||
case 27:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 197 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> *v = (yysemantic_stack_[(3) - (1)].int_vec2);
|
||||
v->append (*(yysemantic_stack_[(3) - (3)].int_vec));
|
||||
@ -568,24 +572,21 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 25:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 184 "knot_parser/knot_parser.yy"
|
||||
case 28:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 206 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.int_vec) = (yysemantic_stack_[(3) - (2)].int_vec); }
|
||||
break;
|
||||
|
||||
case 26:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 186 "knot_parser/knot_parser.yy"
|
||||
case 29:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 208 "knot_parser/knot_parser.yy"
|
||||
{ (yyval.int_vec) = (yysemantic_stack_[(3) - (2)].int_vec); }
|
||||
break;
|
||||
|
||||
case 27:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 191 "knot_parser/knot_parser.yy"
|
||||
case 30:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 213 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<int, 1> *v =
|
||||
new basedvector<int, 1> ();
|
||||
@ -594,10 +595,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 28:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 198 "knot_parser/knot_parser.yy"
|
||||
case 31:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 220 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<int, 1> *v = (yysemantic_stack_[(3) - (1)].int_vec);
|
||||
v->append ((yysemantic_stack_[(3) - (3)].integer));
|
||||
@ -605,10 +605,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 29:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 207 "knot_parser/knot_parser.yy"
|
||||
case 32:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 229 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> *v
|
||||
= new basedvector<basedvector<int, 1>, 1> ();
|
||||
@ -617,10 +616,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 30:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 214 "knot_parser/knot_parser.yy"
|
||||
case 33:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 236 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> *v = (yysemantic_stack_[(3) - (1)].int_vec2);
|
||||
v->append (*(yysemantic_stack_[(3) - (3)].int_vec));
|
||||
@ -628,10 +626,9 @@ namespace yy {
|
||||
}
|
||||
break;
|
||||
|
||||
case 31:
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 223 "knot_parser/knot_parser.yy"
|
||||
case 34:
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 245 "knot_parser/knot_parser.yy"
|
||||
{
|
||||
basedvector<int, 1> *v
|
||||
= new basedvector<int, 1> ();
|
||||
@ -644,12 +641,22 @@ namespace yy {
|
||||
break;
|
||||
|
||||
|
||||
|
||||
/* Line 678 of lalr1.cc */
|
||||
#line 650 "knot_parser/knot_parser.cc"
|
||||
/* Line 661 of lalr1.cc */
|
||||
#line 646 "knot_parser/knot_parser.cc"
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* User semantic actions sometimes alter yychar, and that requires
|
||||
that yytoken be updated with the new translation. We take the
|
||||
approach of translating immediately before every use of yytoken.
|
||||
One alternative is translating here after every semantic action,
|
||||
but that translation would be missed if the semantic action
|
||||
invokes YYABORT, YYACCEPT, or YYERROR immediately after altering
|
||||
yychar. In the case of YYABORT or YYACCEPT, an incorrect
|
||||
destructor might then be invoked immediately. In the case of
|
||||
YYERROR, subsequent parser actions might lead to an incorrect
|
||||
destructor call or verbose syntax error message before the
|
||||
lookahead is translated. */
|
||||
YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc);
|
||||
|
||||
yypop_ (yylen);
|
||||
@ -673,11 +680,17 @@ namespace yy {
|
||||
| yyerrlab -- here on detecting error |
|
||||
`------------------------------------*/
|
||||
yyerrlab:
|
||||
/* Make sure we have latest lookahead translation. See comments at
|
||||
user semantic actions for why this is necessary. */
|
||||
yytoken = yytranslate_ (yychar);
|
||||
|
||||
/* If not already recovering from an error, report this error. */
|
||||
if (!yyerrstatus_)
|
||||
{
|
||||
++yynerrs_;
|
||||
error (yylloc, yysyntax_error_ (yystate));
|
||||
if (yychar == yyempty_)
|
||||
yytoken = yyempty_;
|
||||
error (yylloc, yysyntax_error_ (yystate, yytoken));
|
||||
}
|
||||
|
||||
yyerror_range[1] = yylloc;
|
||||
@ -732,7 +745,7 @@ namespace yy {
|
||||
for (;;)
|
||||
{
|
||||
yyn = yypact_[yystate];
|
||||
if (yyn != yypact_ninf_)
|
||||
if (!yy_pact_value_is_default_ (yyn))
|
||||
{
|
||||
yyn += yyterror_;
|
||||
if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
|
||||
@ -782,7 +795,13 @@ namespace yy {
|
||||
|
||||
yyreturn:
|
||||
if (yychar != yyempty_)
|
||||
yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
|
||||
{
|
||||
/* Make sure we have latest lookahead translation. See comments
|
||||
at user semantic actions for why this is necessary. */
|
||||
yytoken = yytranslate_ (yychar);
|
||||
yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval,
|
||||
&yylloc);
|
||||
}
|
||||
|
||||
/* Do not reclaim the symbols of the rule which action triggered
|
||||
this YYABORT or YYACCEPT. */
|
||||
@ -801,117 +820,76 @@ namespace yy {
|
||||
|
||||
// Generate an error message.
|
||||
std::string
|
||||
knot_parser::yysyntax_error_ (int yystate)
|
||||
knot_parser::yysyntax_error_ (int, int)
|
||||
{
|
||||
std::string res;
|
||||
YYUSE (yystate);
|
||||
#if YYERROR_VERBOSE
|
||||
int yyn = yypact_[yystate];
|
||||
if (yypact_ninf_ < yyn && yyn <= yylast_)
|
||||
{
|
||||
/* Start YYX at -YYN if negative to avoid negative indexes in
|
||||
YYCHECK. */
|
||||
int yyxbegin = yyn < 0 ? -yyn : 0;
|
||||
|
||||
/* Stay within bounds of both yycheck and yytname. */
|
||||
int yychecklim = yylast_ - yyn + 1;
|
||||
int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
|
||||
int count = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != yyterror_)
|
||||
++count;
|
||||
|
||||
// FIXME: This method of building the message is not compatible
|
||||
// with internationalization. It should work like yacc.c does it.
|
||||
// That is, first build a string that looks like this:
|
||||
// "syntax error, unexpected %s or %s or %s"
|
||||
// Then, invoke YY_ on this string.
|
||||
// Finally, use the string as a format to output
|
||||
// yytname_[tok], etc.
|
||||
// Until this gets fixed, this message appears in English only.
|
||||
res = "syntax error, unexpected ";
|
||||
res += yytnamerr_ (yytname_[tok]);
|
||||
if (count < 5)
|
||||
{
|
||||
count = 0;
|
||||
for (int x = yyxbegin; x < yyxend; ++x)
|
||||
if (yycheck_[x + yyn] == x && x != yyterror_)
|
||||
{
|
||||
res += (!count++) ? ", expecting " : " or ";
|
||||
res += yytnamerr_ (yytname_[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
res = YY_("syntax error");
|
||||
return res;
|
||||
return YY_("syntax error");
|
||||
}
|
||||
|
||||
|
||||
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
|
||||
STATE-NUM. */
|
||||
const signed char knot_parser::yypact_ninf_ = -36;
|
||||
const signed char knot_parser::yypact_ninf_ = -39;
|
||||
const signed char
|
||||
knot_parser::yypact_[] =
|
||||
{
|
||||
-1, 10, -9, 25, 26, 37, 9, -36, 43, -36,
|
||||
-36, -36, -36, -36, -36, -36, -36, -36, -36, 41,
|
||||
42, -7, -3, 44, 24, 45, -36, -36, -36, 30,
|
||||
46, 46, 7, -36, 11, -36, -36, 33, 12, 15,
|
||||
-4, 48, 34, 49, 16, -2, -36, 0, -36, 47,
|
||||
-36, -36, -36, 51, 0, -36, 53, 38, -36, -36,
|
||||
-36, -36, -36, 50, 39, 55, -36, -36, 52, 57,
|
||||
54, 58, 59, -36
|
||||
-1, 10, -9, 25, 26, 37, 9, -39, 43, -1,
|
||||
-39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
|
||||
-39, 41, 42, -7, -3, 44, 24, 45, -39, -1,
|
||||
-39, -39, 30, 46, 46, 7, -39, 11, -39, -39,
|
||||
33, 12, 15, -4, 48, 34, 49, 16, -2, -39,
|
||||
0, -39, 47, -39, -39, -39, 51, 0, -39, 53,
|
||||
38, -39, -39, -39, -39, -39, 50, 39, 55, -39,
|
||||
-39, 52, 57, 54, 58, 59, -39
|
||||
};
|
||||
|
||||
/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
|
||||
doesn't specify something else to do. Zero means the default is an
|
||||
error. */
|
||||
/* YYDEFACT[S] -- default reduction number in state S. Performed when
|
||||
YYTABLE doesn't specify something else to do. Zero means the
|
||||
default is an error. */
|
||||
const unsigned char
|
||||
knot_parser::yydefact_[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 20, 0, 2,
|
||||
3, 4, 5, 6, 7, 9, 8, 21, 22, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 10, 11, 0,
|
||||
0, 0, 0, 23, 0, 29, 27, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 13, 0, 14, 0,
|
||||
17, 16, 15, 0, 0, 12, 0, 0, 26, 25,
|
||||
24, 30, 28, 0, 0, 0, 19, 18, 0, 0,
|
||||
0, 0, 0, 31
|
||||
0, 0, 0, 0, 0, 0, 0, 23, 0, 2,
|
||||
3, 5, 6, 7, 8, 9, 10, 12, 11, 24,
|
||||
25, 0, 0, 0, 0, 0, 0, 0, 1, 4,
|
||||
13, 14, 0, 0, 0, 0, 26, 0, 32, 30,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 16,
|
||||
0, 17, 0, 20, 19, 18, 0, 0, 15, 0,
|
||||
0, 29, 28, 27, 33, 31, 0, 0, 0, 22,
|
||||
21, 0, 0, 0, 0, 0, 34
|
||||
};
|
||||
|
||||
/* YYPGOTO[NTERM-NUM]. */
|
||||
const signed char
|
||||
knot_parser::yypgoto_[] =
|
||||
{
|
||||
-36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
|
||||
40, 56, -35, 8, -36, 13
|
||||
-39, -39, 62, -39, -39, -39, -39, -39, -39, -39,
|
||||
-39, -39, 40, 56, -38, 5, -39, 13
|
||||
};
|
||||
|
||||
/* YYDEFGOTO[NTERM-NUM]. */
|
||||
const signed char
|
||||
knot_parser::yydefgoto_[] =
|
||||
{
|
||||
-1, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
20, 32, 33, 39, 34, 35
|
||||
-1, 8, 29, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 22, 35, 36, 42, 37, 38
|
||||
};
|
||||
|
||||
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
|
||||
positive, shift that token. If negative, reduce the rule which
|
||||
number is the opposite. If zero, do what YYDEFACT says. */
|
||||
number is the opposite. If YYTABLE_NINF_, syntax error. */
|
||||
const signed char knot_parser::yytable_ninf_ = -1;
|
||||
const unsigned char
|
||||
knot_parser::yytable_[] =
|
||||
{
|
||||
36, 29, 1, 2, 3, 4, 5, 21, 6, 30,
|
||||
7, 37, 60, 30, 31, 54, 30, 53, 31, 63,
|
||||
59, 31, 17, 18, 46, 19, 47, 25, 48, 51,
|
||||
49, 47, 52, 58, 53, 53, 17, 18, 44, 45,
|
||||
24, 22, 23, 26, 27, 28, 43, 40, 42, 36,
|
||||
50, 55, 57, 56, 62, 29, 64, 65, 68, 67,
|
||||
70, 72, 61, 0, 41, 0, 0, 66, 0, 0,
|
||||
0, 69, 0, 71, 0, 0, 73, 0, 38
|
||||
39, 32, 1, 2, 3, 4, 5, 23, 6, 33,
|
||||
7, 40, 63, 33, 34, 57, 33, 56, 34, 66,
|
||||
62, 34, 19, 20, 49, 21, 50, 27, 51, 54,
|
||||
52, 50, 55, 61, 56, 56, 19, 20, 47, 48,
|
||||
26, 24, 25, 28, 30, 31, 46, 43, 45, 39,
|
||||
53, 58, 60, 59, 65, 32, 67, 68, 71, 70,
|
||||
73, 75, 9, 0, 0, 64, 44, 69, 0, 0,
|
||||
0, 72, 0, 74, 0, 0, 76, 0, 0, 0,
|
||||
41
|
||||
};
|
||||
|
||||
/* YYCHECK. */
|
||||
@ -919,13 +897,14 @@ namespace yy {
|
||||
knot_parser::yycheck_[] =
|
||||
{
|
||||
3, 8, 3, 4, 5, 6, 7, 16, 9, 16,
|
||||
11, 14, 47, 16, 21, 19, 16, 19, 21, 54,
|
||||
11, 14, 50, 16, 21, 19, 16, 19, 21, 57,
|
||||
22, 21, 12, 13, 17, 15, 19, 18, 17, 17,
|
||||
19, 19, 17, 17, 19, 19, 12, 13, 30, 31,
|
||||
19, 19, 17, 17, 19, 19, 12, 13, 33, 34,
|
||||
3, 16, 16, 0, 3, 3, 16, 3, 3, 3,
|
||||
17, 3, 3, 19, 3, 8, 3, 19, 3, 20,
|
||||
3, 3, 49, -1, 24, -1, -1, 17, -1, -1,
|
||||
-1, 19, -1, 19, -1, -1, 17, -1, 22
|
||||
3, 3, 0, -1, -1, 52, 26, 17, -1, -1,
|
||||
-1, 19, -1, 19, -1, -1, 17, -1, -1, -1,
|
||||
24
|
||||
};
|
||||
|
||||
/* STOS_[STATE-NUM] -- The (internal number of the) accessing
|
||||
@ -934,13 +913,13 @@ namespace yy {
|
||||
knot_parser::yystos_[] =
|
||||
{
|
||||
0, 3, 4, 5, 6, 7, 9, 11, 24, 25,
|
||||
26, 27, 28, 29, 30, 31, 32, 12, 13, 15,
|
||||
33, 16, 16, 16, 3, 18, 0, 3, 3, 8,
|
||||
16, 21, 34, 35, 37, 38, 3, 14, 34, 36,
|
||||
3, 33, 3, 16, 36, 36, 17, 19, 17, 19,
|
||||
17, 17, 17, 19, 19, 3, 19, 3, 17, 22,
|
||||
35, 38, 3, 35, 3, 19, 17, 20, 3, 19,
|
||||
3, 19, 3, 17
|
||||
26, 27, 28, 29, 30, 31, 32, 33, 34, 12,
|
||||
13, 15, 35, 16, 16, 16, 3, 18, 0, 25,
|
||||
3, 3, 8, 16, 21, 36, 37, 39, 40, 3,
|
||||
14, 36, 38, 3, 35, 3, 16, 38, 38, 17,
|
||||
19, 17, 19, 17, 17, 17, 19, 19, 3, 19,
|
||||
3, 17, 22, 37, 40, 3, 37, 3, 19, 17,
|
||||
20, 3, 19, 3, 19, 3, 17
|
||||
};
|
||||
|
||||
#if YYDEBUG
|
||||
@ -959,23 +938,23 @@ namespace yy {
|
||||
const unsigned char
|
||||
knot_parser::yyr1_[] =
|
||||
{
|
||||
0, 23, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 26, 27, 28, 28, 29, 29, 29, 30, 31,
|
||||
32, 33, 33, 34, 34, 35, 35, 36, 36, 37,
|
||||
37, 38
|
||||
0, 23, 24, 25, 25, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 27, 28, 29, 30, 30, 31, 31,
|
||||
31, 32, 33, 34, 35, 35, 36, 36, 37, 37,
|
||||
38, 38, 39, 39, 40
|
||||
};
|
||||
|
||||
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
|
||||
const unsigned char
|
||||
knot_parser::yyr2_[] =
|
||||
{
|
||||
0, 2, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
3, 3, 4, 4, 4, 4, 4, 4, 6, 6,
|
||||
1, 1, 1, 1, 3, 3, 3, 1, 3, 1,
|
||||
3, 10
|
||||
0, 2, 1, 1, 2, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 3, 3, 4, 4, 4, 4, 4,
|
||||
4, 6, 6, 1, 1, 1, 1, 3, 3, 3,
|
||||
1, 3, 1, 3, 10
|
||||
};
|
||||
|
||||
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
|
||||
#if YYDEBUG
|
||||
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
|
||||
First, the terminals, then, starting at \a yyntokens_, nonterminals. */
|
||||
const char*
|
||||
@ -983,30 +962,30 @@ namespace yy {
|
||||
{
|
||||
"\"end of file\"", "error", "$undefined", "INT", "PD", "DT", "BR",
|
||||
"LINK", "X", "T", "U", "UNKNOT", "ALT", "NONALT", "STRING", "'_'", "'['",
|
||||
"']'", "'('", "','", "')'", "'{'", "'}'", "$accept", "knot",
|
||||
"rolfsen_knot", "htw_knot", "mt_link", "planar_diagram", "dt",
|
||||
"']'", "'('", "','", "')'", "'{'", "'}'", "$accept", "entry", "knot",
|
||||
"knot_1", "rolfsen_knot", "htw_knot", "mt_link", "planar_diagram", "dt",
|
||||
"torus_link", "braid", "unknot", "alt_spec", "int_vec2", "int_vec",
|
||||
"int_vec_1", "crossing_vec", "crossing", 0
|
||||
"int_vec_1", "crossing_vec", "crossing", YY_NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#if YYDEBUG
|
||||
|
||||
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
|
||||
const knot_parser::rhs_number_type
|
||||
knot_parser::yyrhs_[] =
|
||||
{
|
||||
24, 0, -1, 25, -1, 26, -1, 27, -1, 28,
|
||||
-1, 29, -1, 30, -1, 32, -1, 31, -1, 3,
|
||||
15, 3, -1, 3, 33, 3, -1, 7, 3, 33,
|
||||
3, -1, 4, 16, 34, 17, -1, 4, 16, 37,
|
||||
17, -1, 5, 16, 36, 17, -1, 5, 16, 34,
|
||||
17, -1, 5, 16, 14, 17, -1, 9, 18, 3,
|
||||
19, 3, 20, -1, 6, 16, 3, 19, 35, 17,
|
||||
-1, 11, -1, 12, -1, 13, -1, 35, -1, 34,
|
||||
19, 35, -1, 21, 36, 22, -1, 16, 36, 17,
|
||||
-1, 3, -1, 36, 19, 3, -1, 38, -1, 37,
|
||||
19, 38, -1, 8, 16, 3, 19, 3, 19, 3,
|
||||
19, 3, 17, -1
|
||||
24, 0, -1, 25, -1, 26, -1, 25, 25, -1,
|
||||
27, -1, 28, -1, 29, -1, 30, -1, 31, -1,
|
||||
32, -1, 34, -1, 33, -1, 3, 15, 3, -1,
|
||||
3, 35, 3, -1, 7, 3, 35, 3, -1, 4,
|
||||
16, 36, 17, -1, 4, 16, 39, 17, -1, 5,
|
||||
16, 38, 17, -1, 5, 16, 36, 17, -1, 5,
|
||||
16, 14, 17, -1, 9, 18, 3, 19, 3, 20,
|
||||
-1, 6, 16, 3, 19, 37, 17, -1, 11, -1,
|
||||
12, -1, 13, -1, 37, -1, 36, 19, 37, -1,
|
||||
21, 38, 22, -1, 16, 38, 17, -1, 3, -1,
|
||||
38, 19, 3, -1, 40, -1, 39, 19, 40, -1,
|
||||
8, 16, 3, 19, 3, 19, 3, 19, 3, 17,
|
||||
-1
|
||||
};
|
||||
|
||||
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
|
||||
@ -1014,20 +993,20 @@ namespace yy {
|
||||
const unsigned char
|
||||
knot_parser::yyprhs_[] =
|
||||
{
|
||||
0, 0, 3, 5, 7, 9, 11, 13, 15, 17,
|
||||
19, 23, 27, 32, 37, 42, 47, 52, 57, 64,
|
||||
71, 73, 75, 77, 79, 83, 87, 91, 93, 97,
|
||||
99, 103
|
||||
0, 0, 3, 5, 7, 10, 12, 14, 16, 18,
|
||||
20, 22, 24, 26, 30, 34, 39, 44, 49, 54,
|
||||
59, 64, 71, 78, 80, 82, 84, 86, 90, 94,
|
||||
98, 100, 104, 106, 110
|
||||
};
|
||||
|
||||
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
||||
const unsigned char
|
||||
knot_parser::yyrline_[] =
|
||||
{
|
||||
0, 55, 55, 56, 57, 58, 59, 60, 61, 62,
|
||||
66, 84, 103, 122, 124, 129, 135, 137, 142, 147,
|
||||
152, 162, 163, 167, 174, 183, 185, 190, 197, 206,
|
||||
213, 222
|
||||
0, 59, 59, 67, 68, 77, 78, 79, 80, 81,
|
||||
82, 83, 84, 88, 106, 125, 144, 146, 151, 157,
|
||||
159, 164, 169, 174, 184, 185, 189, 196, 205, 207,
|
||||
212, 219, 228, 235, 244
|
||||
};
|
||||
|
||||
// Print the state stack on the debug stream.
|
||||
@ -1102,10 +1081,10 @@ namespace yy {
|
||||
}
|
||||
|
||||
const int knot_parser::yyeof_ = 0;
|
||||
const int knot_parser::yylast_ = 78;
|
||||
const int knot_parser::yynnts_ = 16;
|
||||
const int knot_parser::yylast_ = 80;
|
||||
const int knot_parser::yynnts_ = 18;
|
||||
const int knot_parser::yyempty_ = -2;
|
||||
const int knot_parser::yyfinal_ = 26;
|
||||
const int knot_parser::yyfinal_ = 28;
|
||||
const int knot_parser::yyterror_ = 1;
|
||||
const int knot_parser::yyerrcode_ = 256;
|
||||
const int knot_parser::yyntokens_ = 23;
|
||||
@ -1115,13 +1094,10 @@ namespace yy {
|
||||
|
||||
|
||||
} // yy
|
||||
|
||||
/* Line 1054 of lalr1.cc */
|
||||
#line 1121 "knot_parser/knot_parser.cc"
|
||||
|
||||
|
||||
/* Line 1056 of lalr1.cc */
|
||||
#line 233 "knot_parser/knot_parser.yy"
|
||||
/* Line 1106 of lalr1.cc */
|
||||
#line 1099 "knot_parser/knot_parser.cc"
|
||||
/* Line 1107 of lalr1.cc */
|
||||
#line 255 "knot_parser/knot_parser.yy"
|
||||
|
||||
|
||||
void
|
||||
@ -1145,4 +1121,3 @@ parse_knot (const char *s)
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.3. */
|
||||
/* A Bison parser, made by GNU Bison 2.6.5. */
|
||||
|
||||
/* Skeleton interface for Bison LALR(1) parsers in C++
|
||||
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -31,41 +30,30 @@
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/**
|
||||
** \file knot_parser/knot_parser.hh
|
||||
** Define the yy::parser class.
|
||||
*/
|
||||
|
||||
/* C++ LALR(1) parser skeleton written by Akim Demaille. */
|
||||
|
||||
#ifndef PARSER_HEADER_H
|
||||
# define PARSER_HEADER_H
|
||||
#ifndef YY_YY_KNOT_PARSER_KNOT_PARSER_HH_INCLUDED
|
||||
# define YY_YY_KNOT_PARSER_KNOT_PARSER_HH_INCLUDED
|
||||
|
||||
/* "%code requires" blocks. */
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
/* Line 36 of lalr1.cc */
|
||||
#line 11 "knot_parser/knot_parser.yy"
|
||||
|
||||
#include <knotkit.h>
|
||||
|
||||
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
#line 50 "knot_parser/knot_parser.hh"
|
||||
/* Line 36 of lalr1.cc */
|
||||
#line 52 "knot_parser/knot_parser.hh"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "stack.hh"
|
||||
|
||||
|
||||
namespace yy {
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
#line 61 "knot_parser/knot_parser.hh"
|
||||
class position;
|
||||
class location;
|
||||
|
||||
} // yy
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
#line 68 "knot_parser/knot_parser.hh"
|
||||
|
||||
#include "location.hh"
|
||||
|
||||
/* Enabling traces. */
|
||||
@ -73,43 +61,10 @@ namespace yy {
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
|
||||
/* Enabling verbose error messages. */
|
||||
#ifdef YYERROR_VERBOSE
|
||||
# undef YYERROR_VERBOSE
|
||||
# define YYERROR_VERBOSE 1
|
||||
#else
|
||||
# define YYERROR_VERBOSE 0
|
||||
#endif
|
||||
|
||||
/* Enabling the token table. */
|
||||
#ifndef YYTOKEN_TABLE
|
||||
# define YYTOKEN_TABLE 0
|
||||
#endif
|
||||
|
||||
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
|
||||
If N is 0, then set CURRENT to the empty location which ends
|
||||
the previous symbol: RHS[0] (always defined). */
|
||||
|
||||
#ifndef YYLLOC_DEFAULT
|
||||
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
||||
do { \
|
||||
if (N) \
|
||||
{ \
|
||||
(Current).begin = (Rhs)[1].begin; \
|
||||
(Current).end = (Rhs)[N].end; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(Current).begin = (Current).end = (Rhs)[0].end; \
|
||||
} \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
|
||||
namespace yy {
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
#line 113 "knot_parser/knot_parser.hh"
|
||||
/* Line 36 of lalr1.cc */
|
||||
#line 68 "knot_parser/knot_parser.hh"
|
||||
|
||||
/// A Bison parser.
|
||||
class knot_parser
|
||||
@ -119,8 +74,7 @@ namespace yy {
|
||||
#ifndef YYSTYPE
|
||||
union semantic_type
|
||||
{
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
/* Line 36 of lalr1.cc */
|
||||
#line 21 "knot_parser/knot_parser.yy"
|
||||
|
||||
int integer;
|
||||
@ -128,11 +82,11 @@ namespace yy {
|
||||
basedvector<int, 1> *int_vec;
|
||||
basedvector<basedvector<int, 1>, 1> *int_vec2;
|
||||
const char *string;
|
||||
knot_diagram *kd;
|
||||
|
||||
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
#line 136 "knot_parser/knot_parser.hh"
|
||||
/* Line 36 of lalr1.cc */
|
||||
#line 90 "knot_parser/knot_parser.hh"
|
||||
};
|
||||
#else
|
||||
typedef YYSTYPE semantic_type;
|
||||
@ -194,7 +148,7 @@ namespace yy {
|
||||
/// Generate an error message.
|
||||
/// \param state the state where the error occurred.
|
||||
/// \param tok the lookahead token.
|
||||
virtual std::string yysyntax_error_ (int yystate);
|
||||
virtual std::string yysyntax_error_ (int yystate, int tok);
|
||||
|
||||
#if YYDEBUG
|
||||
/// \brief Report a symbol value on the debug stream.
|
||||
@ -230,6 +184,14 @@ namespace yy {
|
||||
/// The location stack.
|
||||
location_stack_type yylocation_stack_;
|
||||
|
||||
/// Whether the given \c yypact_ value indicates a defaulted state.
|
||||
/// \param yyvalue the value to check
|
||||
static bool yy_pact_value_is_default_ (int yyvalue);
|
||||
|
||||
/// Whether the given \c yytable_ value indicates a syntax error.
|
||||
/// \param yyvalue the value to check
|
||||
static bool yy_table_value_is_error_ (int yyvalue);
|
||||
|
||||
/// Internal symbol numbers.
|
||||
typedef unsigned char token_number_type;
|
||||
/* Tables. */
|
||||
@ -237,7 +199,7 @@ namespace yy {
|
||||
static const signed char yypact_[];
|
||||
static const signed char yypact_ninf_;
|
||||
|
||||
/// For a state, default rule to reduce.
|
||||
/// For a state, default reduction number.
|
||||
/// Unless\a yytable_ specifies something else to do.
|
||||
/// Zero means the default is an error.
|
||||
static const unsigned char yydefact_[];
|
||||
@ -261,19 +223,12 @@ namespace yy {
|
||||
/// For a rule, its LHS.
|
||||
static const unsigned char yyr1_[];
|
||||
/// For a rule, its RHS length.
|
||||
static const unsigned char yyr2_[];
|
||||
|
||||
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
|
||||
/// For a symbol, its name in clear.
|
||||
static const char* const yytname_[];
|
||||
#endif
|
||||
|
||||
#if YYERROR_VERBOSE
|
||||
/// Convert the symbol name \a n to a form suitable for a diagnostic.
|
||||
virtual std::string yytnamerr_ (const char *n);
|
||||
#endif
|
||||
static const unsigned char yyr2_[];
|
||||
|
||||
#if YYDEBUG
|
||||
/// For a symbol, its name in clear.
|
||||
static const char* const yytname_[];
|
||||
|
||||
/// A type to store symbol numbers and -1.
|
||||
typedef signed char rhs_number_type;
|
||||
/// A `-1'-separated list of the rules' RHS.
|
||||
@ -328,10 +283,9 @@ namespace yy {
|
||||
};
|
||||
|
||||
} // yy
|
||||
|
||||
/* Line 35 of lalr1.cc */
|
||||
#line 334 "knot_parser/knot_parser.hh"
|
||||
/* Line 36 of lalr1.cc */
|
||||
#line 288 "knot_parser/knot_parser.hh"
|
||||
|
||||
|
||||
|
||||
#endif /* ! defined PARSER_HEADER_H */
|
||||
#endif /* !YY_YY_KNOT_PARSER_KNOT_PARSER_HH_INCLUDED */
|
||||
|
@ -24,6 +24,7 @@ YY_DECL;
|
||||
basedvector<int, 1> *int_vec;
|
||||
basedvector<basedvector<int, 1>, 1> *int_vec2;
|
||||
const char *string;
|
||||
knot_diagram *kd;
|
||||
}
|
||||
|
||||
%code {
|
||||
@ -36,9 +37,12 @@ YY_DECL;
|
||||
|
||||
%token PD DT BR LINK X T
|
||||
%token U UNKNOT
|
||||
|
||||
%token <alternating> ALT NONALT
|
||||
%token <string> STRING
|
||||
|
||||
%type <kd> knot knot_1
|
||||
%type <kd> rolfsen_knot htw_knot mt_link planar_diagram dt torus_link unknot braid
|
||||
%type <alternating> alt_spec
|
||||
|
||||
%type <int_vec> int_vec int_vec_1
|
||||
@ -49,9 +53,27 @@ YY_DECL;
|
||||
|
||||
%%
|
||||
|
||||
%start knot;
|
||||
%start entry;
|
||||
|
||||
entry:
|
||||
knot
|
||||
{
|
||||
parsed_knot = *$1;
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
|
||||
knot:
|
||||
knot_1
|
||||
| knot knot
|
||||
{
|
||||
$$ = new knot_diagram (DISJOINT_UNION, *$1, *$2);
|
||||
delete $1;
|
||||
delete $2;
|
||||
}
|
||||
;
|
||||
|
||||
knot_1:
|
||||
rolfsen_knot
|
||||
| htw_knot
|
||||
| mt_link
|
||||
@ -70,7 +92,7 @@ rolfsen_knot:
|
||||
|
||||
if (n >= 1 && n <= 10
|
||||
&& k >= 1 && k <= rolfsen_crossing_knots (n))
|
||||
parsed_knot = knot_diagram (rolfsen_knot (n, k));
|
||||
$$ = new knot_diagram (rolfsen_knot (n, k));
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "knot_parser: no such Rolfsen knot `%d_%d'\n",
|
||||
@ -89,7 +111,7 @@ htw_knot:
|
||||
|
||||
if (n >= 1 && n <= 16
|
||||
&& k >= 1 && k <= htw_knots (n, alt))
|
||||
parsed_knot = knot_diagram (htw_knot (n, alt, k));
|
||||
$$ = new knot_diagram (htw_knot (n, alt, k));
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "knot_parser: no such HTW knot `%d%c%d'\n",
|
||||
@ -108,7 +130,7 @@ mt_link:
|
||||
|
||||
if (n >= 1 && n <= 14
|
||||
&& k >= 1 && k <= mt_links (n, alt))
|
||||
parsed_knot = knot_diagram (mt_link (n, alt, k));
|
||||
$$ = new knot_diagram (mt_link (n, alt, k));
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "knot_parser: no such MT link `%d%c%d'\n",
|
||||
@ -120,9 +142,9 @@ mt_link:
|
||||
|
||||
planar_diagram:
|
||||
PD '[' int_vec2 ']'
|
||||
{ parsed_knot = knot_diagram (planar_diagram ("<parsed>", *$3)); }
|
||||
{ $$ = new knot_diagram (planar_diagram ("<parsed>", *$3)); }
|
||||
| PD '[' crossing_vec ']'
|
||||
{ parsed_knot = knot_diagram (planar_diagram ("<parsed>", *$3)); }
|
||||
{ $$ = new knot_diagram (planar_diagram ("<parsed>", *$3)); }
|
||||
;
|
||||
|
||||
dt:
|
||||
@ -130,22 +152,22 @@ dt:
|
||||
{
|
||||
basedvector<basedvector<int, 1>, 1> even_labels (1);
|
||||
even_labels[1] = *$3;
|
||||
parsed_knot = knot_diagram (dt_code ("<parsed>", even_labels));
|
||||
$$ = new knot_diagram (dt_code ("<parsed>", even_labels));
|
||||
}
|
||||
| DT '[' int_vec2 ']'
|
||||
{ parsed_knot = knot_diagram (dt_code ("<parsed>", *$3)); }
|
||||
{ $$ = new knot_diagram (dt_code ("<parsed>", *$3)); }
|
||||
| DT '[' STRING ']'
|
||||
{ parsed_knot = knot_diagram (dt_code ("<parsed>", $3)); }
|
||||
{ $$ = new knot_diagram (dt_code ("<parsed>", $3)); }
|
||||
;
|
||||
|
||||
torus_link:
|
||||
T '(' INT ',' INT ')'
|
||||
{ parsed_knot = knot_diagram (torus_knot ($3, $5)); }
|
||||
{ $$ = new knot_diagram (torus_knot ($3, $5)); }
|
||||
;
|
||||
|
||||
braid:
|
||||
BR '[' INT ',' int_vec ']'
|
||||
{ parsed_knot = knot_diagram (braid ($3, *$5)); }
|
||||
{ $$ = new knot_diagram (braid ($3, *$5)); }
|
||||
;
|
||||
|
||||
unknot:
|
||||
@ -154,7 +176,7 @@ unknot:
|
||||
unsigned unknot_ar[1][4] = {
|
||||
{ 2, 1, 3, 4, },
|
||||
};
|
||||
parsed_knot = knot_diagram ("U", 1, unknot_ar);
|
||||
$$ = new knot_diagram ("U", 1, unknot_ar);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.3. */
|
||||
/* A Bison parser, made by GNU Bison 2.6.5. */
|
||||
|
||||
/* Locations for Bison parsers in C++
|
||||
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 2002-2007, 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -32,39 +31,55 @@
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/**
|
||||
** \file location.hh
|
||||
** \file knot_parser/location.hh
|
||||
** Define the yy::location class.
|
||||
*/
|
||||
|
||||
#ifndef BISON_LOCATION_HH
|
||||
# define BISON_LOCATION_HH
|
||||
#ifndef YY_YY_KNOT_PARSER_LOCATION_HH_INCLUDED
|
||||
# define YY_YY_KNOT_PARSER_LOCATION_HH_INCLUDED
|
||||
|
||||
# include <iostream>
|
||||
# include <string>
|
||||
# include "position.hh"
|
||||
|
||||
|
||||
namespace yy {
|
||||
|
||||
/* Line 163 of location.cc */
|
||||
#line 51 "knot_parser/location.hh"
|
||||
/* Line 164 of location.cc */
|
||||
#line 47 "knot_parser/location.hh"
|
||||
|
||||
/// Abstract a location.
|
||||
class location
|
||||
{
|
||||
public:
|
||||
|
||||
/// Construct a location.
|
||||
location ()
|
||||
: begin (), end ()
|
||||
/// Construct a location from \a b to \a e.
|
||||
location (const position& b, const position& e)
|
||||
: begin (b)
|
||||
, end (e)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a 0-width location in \a p.
|
||||
explicit location (const position& p = position ())
|
||||
: begin (p)
|
||||
, end (p)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a 0-width location in \a f, \a l, \a c.
|
||||
explicit location (std::string* f,
|
||||
unsigned int l = 1u,
|
||||
unsigned int c = 1u)
|
||||
: begin (f, l, c)
|
||||
, end (f, l, c)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Initialization.
|
||||
inline void initialize (std::string* fn)
|
||||
void initialize (std::string* f = YY_NULL,
|
||||
unsigned int l = 1u,
|
||||
unsigned int c = 1u)
|
||||
{
|
||||
begin.initialize (fn);
|
||||
begin.initialize (f, l, c);
|
||||
end = begin;
|
||||
}
|
||||
|
||||
@ -72,19 +87,19 @@ namespace yy {
|
||||
** \{ */
|
||||
public:
|
||||
/// Reset initial location to final location.
|
||||
inline void step ()
|
||||
void step ()
|
||||
{
|
||||
begin = end;
|
||||
}
|
||||
|
||||
/// Extend the current location to the COUNT next columns.
|
||||
inline void columns (unsigned int count = 1)
|
||||
void columns (unsigned int count = 1)
|
||||
{
|
||||
end += count;
|
||||
}
|
||||
|
||||
/// Extend the current location to the COUNT next lines.
|
||||
inline void lines (unsigned int count = 1)
|
||||
void lines (unsigned int count = 1)
|
||||
{
|
||||
end.lines (count);
|
||||
}
|
||||
@ -158,8 +173,7 @@ namespace yy {
|
||||
|
||||
|
||||
} // yy
|
||||
/* Line 292 of location.cc */
|
||||
#line 178 "knot_parser/location.hh"
|
||||
|
||||
/* Line 272 of location.cc */
|
||||
#line 164 "knot_parser/location.hh"
|
||||
|
||||
#endif // not BISON_LOCATION_HH
|
||||
#endif /* !YY_YY_KNOT_PARSER_LOCATION_HH_INCLUDED */
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.3. */
|
||||
/* A Bison parser, made by GNU Bison 2.6.5. */
|
||||
|
||||
/* Positions for Bison parsers in C++
|
||||
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 2002-2007, 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -32,60 +31,71 @@
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/**
|
||||
** \file position.hh
|
||||
** \file knot_parser/position.hh
|
||||
** Define the yy::position class.
|
||||
*/
|
||||
|
||||
#ifndef BISON_POSITION_HH
|
||||
# define BISON_POSITION_HH
|
||||
#ifndef YY_YY_KNOT_PARSER_POSITION_HH_INCLUDED
|
||||
# define YY_YY_KNOT_PARSER_POSITION_HH_INCLUDED
|
||||
|
||||
# include <algorithm> // std::max
|
||||
# include <iostream>
|
||||
# include <string>
|
||||
# include <algorithm>
|
||||
|
||||
# ifndef YY_NULL
|
||||
# if defined __cplusplus && 201103L <= __cplusplus
|
||||
# define YY_NULL nullptr
|
||||
# else
|
||||
# define YY_NULL 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
||||
namespace yy {
|
||||
|
||||
/* Line 38 of location.cc */
|
||||
#line 51 "knot_parser/position.hh"
|
||||
#line 57 "knot_parser/position.hh"
|
||||
/// Abstract a position.
|
||||
class position
|
||||
{
|
||||
public:
|
||||
|
||||
/// Construct a position.
|
||||
position ()
|
||||
: filename (0), line (1), column (1)
|
||||
explicit position (std::string* f = YY_NULL,
|
||||
unsigned int l = 1u,
|
||||
unsigned int c = 1u)
|
||||
: filename (f)
|
||||
, line (l)
|
||||
, column (c)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Initialization.
|
||||
inline void initialize (std::string* fn)
|
||||
void initialize (std::string* fn = YY_NULL,
|
||||
unsigned int l = 1u,
|
||||
unsigned int c = 1u)
|
||||
{
|
||||
filename = fn;
|
||||
line = 1;
|
||||
column = 1;
|
||||
line = l;
|
||||
column = c;
|
||||
}
|
||||
|
||||
/** \name Line and Column related manipulators
|
||||
** \{ */
|
||||
public:
|
||||
/// (line related) Advance to the COUNT next lines.
|
||||
inline void lines (int count = 1)
|
||||
void lines (int count = 1)
|
||||
{
|
||||
column = 1;
|
||||
column = 1u;
|
||||
line += count;
|
||||
}
|
||||
|
||||
/// (column related) Advance to the COUNT next columns.
|
||||
inline void columns (int count = 1)
|
||||
void columns (int count = 1)
|
||||
{
|
||||
column = std::max (1u, column + count);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
public:
|
||||
/// File name to which this position refers.
|
||||
std::string* filename;
|
||||
/// Current line number.
|
||||
@ -95,7 +105,7 @@ namespace yy {
|
||||
};
|
||||
|
||||
/// Add and assign a position.
|
||||
inline const position&
|
||||
inline position&
|
||||
operator+= (position& res, const int width)
|
||||
{
|
||||
res.columns (width);
|
||||
@ -111,7 +121,7 @@ namespace yy {
|
||||
}
|
||||
|
||||
/// Add and assign a position.
|
||||
inline const position&
|
||||
inline position&
|
||||
operator-= (position& res, const int width)
|
||||
{
|
||||
return res += -width;
|
||||
@ -156,7 +166,6 @@ namespace yy {
|
||||
|
||||
|
||||
} // yy
|
||||
|
||||
/* Line 145 of location.cc */
|
||||
#line 162 "knot_parser/position.hh"
|
||||
#endif // not BISON_POSITION_HH
|
||||
/* Line 149 of location.cc */
|
||||
#line 171 "knot_parser/position.hh"
|
||||
#endif /* !YY_YY_KNOT_PARSER_POSITION_HH_INCLUDED */
|
||||
|
@ -1,9 +1,8 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.3. */
|
||||
/* A Bison parser, made by GNU Bison 2.6.5. */
|
||||
|
||||
/* Stack handling for Bison parsers in C++
|
||||
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -31,21 +30,24 @@
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
#ifndef BISON_STACK_HH
|
||||
# define BISON_STACK_HH
|
||||
/**
|
||||
** \file knot_parser/stack.hh
|
||||
** Define the yy::stack class.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#ifndef YY_YY_KNOT_PARSER_STACK_HH_INCLUDED
|
||||
# define YY_YY_KNOT_PARSER_STACK_HH_INCLUDED
|
||||
|
||||
# include <deque>
|
||||
|
||||
|
||||
namespace yy {
|
||||
|
||||
/* Line 1067 of lalr1.cc */
|
||||
#line 44 "knot_parser/stack.hh"
|
||||
/* Line 37 of stack.hh */
|
||||
#line 47 "knot_parser/stack.hh"
|
||||
template <class T, class S = std::deque<T> >
|
||||
class stack
|
||||
{
|
||||
public:
|
||||
|
||||
// Hide our reversed order.
|
||||
typedef typename S::reverse_iterator iterator;
|
||||
typedef typename S::const_reverse_iterator const_iterator;
|
||||
@ -84,7 +86,7 @@ namespace yy {
|
||||
pop (unsigned int n = 1)
|
||||
{
|
||||
for (; n; --n)
|
||||
seq_.pop_front ();
|
||||
seq_.pop_front ();
|
||||
}
|
||||
|
||||
inline
|
||||
@ -98,7 +100,6 @@ namespace yy {
|
||||
inline const_iterator end () const { return seq_.rend (); }
|
||||
|
||||
private:
|
||||
|
||||
S seq_;
|
||||
};
|
||||
|
||||
@ -107,10 +108,9 @@ namespace yy {
|
||||
class slice
|
||||
{
|
||||
public:
|
||||
|
||||
slice (const S& stack,
|
||||
unsigned int range) : stack_ (stack),
|
||||
range_ (range)
|
||||
slice (const S& stack, unsigned int range)
|
||||
: stack_ (stack)
|
||||
, range_ (range)
|
||||
{
|
||||
}
|
||||
|
||||
@ -122,15 +122,12 @@ namespace yy {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const S& stack_;
|
||||
unsigned int range_;
|
||||
};
|
||||
|
||||
} // yy
|
||||
/* Line 119 of stack.hh */
|
||||
#line 132 "knot_parser/stack.hh"
|
||||
|
||||
/* Line 1153 of lalr1.cc */
|
||||
#line 134 "knot_parser/stack.hh"
|
||||
|
||||
#endif // not BISON_STACK_HH[]dnl
|
||||
|
||||
#endif /* !YY_YY_KNOT_PARSER_STACK_HH_INCLUDED */
|
||||
|
229
knot_tables.cpp
229
knot_tables.cpp
@ -402,7 +402,7 @@ htw_knot (unsigned n, bool alternating, unsigned k)
|
||||
before += htw_alternating[i];
|
||||
off = 8 * (before + k - 1);
|
||||
|
||||
file = HOME "alternating";
|
||||
file = HOME "/alternating";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -411,7 +411,7 @@ htw_knot (unsigned n, bool alternating, unsigned k)
|
||||
before += htw_nonalternating[i];
|
||||
off = 10 * (before + k - 1);
|
||||
|
||||
file = HOME "nonalternating";
|
||||
file = HOME "/nonalternating";
|
||||
}
|
||||
FILE *fp = fopen (file, "r");
|
||||
if (fp == 0)
|
||||
@ -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)
|
||||
{
|
||||
@ -507,7 +514,7 @@ mt_link (unsigned n, bool alternating, unsigned k)
|
||||
|
||||
char buf[1000];
|
||||
|
||||
sprintf (buf, HOME "mtlinks/hyperbolic_data_%02d%c", n, alternating ? 'a' : 'n');
|
||||
sprintf (buf, HOME "/mtlinks/hyperbolic_data_%02d%c", n, alternating ? 'a' : 'n');
|
||||
FILE *fp = fopen (buf, "r");
|
||||
if (fp == 0)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -594,7 +614,7 @@ torus_knot (unsigned n_strands, unsigned n_shifts)
|
||||
return planar_diagram (std::string (buf), crossings);
|
||||
}
|
||||
|
||||
planar_diagram
|
||||
knot_diagram
|
||||
braid (unsigned n_strands, unsigned n_twists, int twists_ar[])
|
||||
{
|
||||
basedvector<int, 1> twists (n_twists);
|
||||
@ -603,10 +623,9 @@ braid (unsigned n_strands, unsigned n_twists, int twists_ar[])
|
||||
return braid (n_strands, twists);
|
||||
}
|
||||
|
||||
planar_diagram
|
||||
knot_diagram
|
||||
braid (unsigned n_strands, const basedvector<int, 1> &twists)
|
||||
{
|
||||
unsigned n_crossings = twists.size ();
|
||||
unsigned e = 0;
|
||||
|
||||
basedvector<unsigned, 1> final_strands (n_strands);
|
||||
@ -622,22 +641,44 @@ braid (unsigned n_strands, const basedvector<int, 1> &twists)
|
||||
last_twist[i] = 0;
|
||||
for (unsigned i = 1; i <= twists.size (); i ++)
|
||||
{
|
||||
unsigned t = std::abs (twists[i]);
|
||||
unsigned t = abs (twists[i]);
|
||||
last_twist[t] = i;
|
||||
last_twist[t + 1] = i;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
for (unsigned i = 1; i <= n_strands; i ++)
|
||||
assert (last_twist[i] != 0);
|
||||
#endif
|
||||
|
||||
basedvector<basedvector<int, 1>, 1> crossings (n_crossings);
|
||||
unsigned n_crossings = twists.size ();
|
||||
for (unsigned i = 1; i <= n_strands; i ++)
|
||||
{
|
||||
if (last_twist[i] == 0)
|
||||
n_crossings ++;
|
||||
}
|
||||
|
||||
basedvector<basedvector<unsigned, 1>, 1> crossings (n_crossings);
|
||||
for (unsigned i = 1; i <= n_crossings; i ++)
|
||||
crossings[i] = basedvector<int, 1> (4);
|
||||
crossings[i] = basedvector<unsigned, 1> (4);
|
||||
|
||||
unsigned c = twists.size ();
|
||||
for (unsigned i = 1; i <= n_strands; i ++)
|
||||
{
|
||||
if (last_twist[i] == 0)
|
||||
{
|
||||
++ c;
|
||||
unsigned e1 = strands[i];
|
||||
unsigned e2 = ++ e;
|
||||
|
||||
strands[i] = final_strands[i] = 0;
|
||||
|
||||
crossings[c][1] = edge_from_ept (e1);
|
||||
crossings[c][2] = edge_to_ept (e2);
|
||||
crossings[c][3] = edge_from_ept (e2);
|
||||
crossings[c][4] = edge_to_ept (e1);
|
||||
}
|
||||
}
|
||||
assert (c == n_crossings);
|
||||
|
||||
for (unsigned i = 1; i <= twists.size (); i ++)
|
||||
{
|
||||
unsigned t = std::abs (twists[i]);
|
||||
unsigned t = abs (twists[i]);
|
||||
unsigned e1 = strands[t],
|
||||
e4 = strands[t + 1];
|
||||
unsigned e2, e3;
|
||||
@ -668,27 +709,30 @@ braid (unsigned n_strands, const basedvector<int, 1> &twists)
|
||||
|
||||
if (twists[i] > 0)
|
||||
{
|
||||
crossings[i][1] = e1;
|
||||
crossings[i][2] = e2;
|
||||
crossings[i][3] = e3;
|
||||
crossings[i][4] = e4;
|
||||
crossings[i][1] = edge_to_ept (e1);
|
||||
crossings[i][2] = edge_from_ept (e2);
|
||||
crossings[i][3] = edge_from_ept (e3);
|
||||
crossings[i][4] = edge_to_ept (e4);
|
||||
}
|
||||
else
|
||||
{
|
||||
crossings[i][1] = e2;
|
||||
crossings[i][2] = e3;
|
||||
crossings[i][3] = e4;
|
||||
crossings[i][4] = e1;
|
||||
crossings[i][1] = edge_from_ept (e2);
|
||||
crossings[i][2] = edge_from_ept (e3);
|
||||
crossings[i][3] = edge_to_ept (e4);
|
||||
crossings[i][4] = edge_to_ept (e1);
|
||||
}
|
||||
}
|
||||
|
||||
assert (e == n_crossings * 2);
|
||||
#ifndef NDEBUG
|
||||
for (unsigned i = 1; i <= n_strands; i ++)
|
||||
assert (final_strands[i] == 0);
|
||||
{
|
||||
assert (strands[i] == 0);
|
||||
assert (final_strands[i] == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return planar_diagram ("abraid", crossings);
|
||||
return knot_diagram ("abraid", crossings);
|
||||
}
|
||||
|
||||
basedvector<basedvector<unsigned, 1>, 1>
|
||||
@ -697,7 +741,7 @@ mutant_knot_groups (unsigned n)
|
||||
assert (11 <= n && n <= 15);
|
||||
|
||||
char buf[1000];
|
||||
sprintf (buf, HOME "mutant_knot_groups/dat%d", n);
|
||||
sprintf (buf, HOME "/mutant_knot_groups/dat%d", n);
|
||||
|
||||
FILE *fp = fopen (buf, "r");
|
||||
if (fp == 0)
|
||||
@ -728,3 +772,138 @@ 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];
|
||||
|
||||
#if 0
|
||||
sprintf (buf, "knot_desc(%d, %d, %d)", (int)t, i, j);
|
||||
return buf;
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
84
knotkit.h
84
knotkit.h
@ -14,13 +14,90 @@ class knot_diagram;
|
||||
#include <dt_code.h>
|
||||
#include <knot_diagram.h>
|
||||
|
||||
#include <simplify_chain_complex.h>
|
||||
#include <sseq.h>
|
||||
#include <smoothing.h>
|
||||
#include <cobordism.h>
|
||||
|
||||
#include <cube.h>
|
||||
#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;
|
||||
|
||||
hash_t hash_self () const
|
||||
{
|
||||
return hash_combine (hash ((int)t),
|
||||
hash_combine (hash (i),
|
||||
hash (j)));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -31,12 +108,15 @@ 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);
|
||||
|
||||
planar_diagram braid (unsigned n_strands, const basedvector<int, 1> &twists);
|
||||
planar_diagram braid (unsigned n_strands, unsigned n_twists, int twists_ar[]);
|
||||
knot_diagram braid (unsigned n_strands, const basedvector<int, 1> &twists);
|
||||
knot_diagram braid (unsigned n_strands, unsigned n_twists, int twists_ar[]);
|
||||
|
||||
knot_diagram parse_knot (const char *s);
|
||||
resolution_diagram parse_resolution_diagram (const char *s);
|
||||
|
@ -1,23 +1,29 @@
|
||||
|
||||
/* wrapper for std::unordered_map */
|
||||
|
||||
template<class K>
|
||||
struct hasher : public std::unary_function<K, hash_t>
|
||||
{
|
||||
hash_t operator () (const K &k) const { return hash (k); }
|
||||
};
|
||||
|
||||
template<class K, class V>
|
||||
class hashmap : public map_wrapper<std::tr1::unordered_map<K, V, hasher<K> >, K, V>
|
||||
class hashmap : public map_wrapper<std::unordered_map<K, V, hasher<K> >, K, V>
|
||||
{
|
||||
typedef map_wrapper<std::tr1::unordered_map<K, V, hasher<K> >, K, V> base;
|
||||
typedef map_wrapper<std::unordered_map<K, V, hasher<K> >, K, V> base;
|
||||
|
||||
public:
|
||||
hashmap () { }
|
||||
hashmap (const hashmap &m) : base(m) { }
|
||||
hashmap (copy, const hashmap &m) : base(COPY, m) { }
|
||||
hashmap (initializer_list<std::pair<const K, V> > il) : base(il) { }
|
||||
hashmap (reader &r) : base(r) { }
|
||||
~hashmap () { }
|
||||
|
||||
hashmap &operator = (const hashmap &m) { base::operator = (m); return *this; }
|
||||
hashmap &operator = (initializer_list<std::pair<const K, V> > il)
|
||||
{
|
||||
base::operator = (il);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class K, class V>
|
||||
using hashmap_iter = map_wrapper_iter<std::unordered_map<K, V>, K, V>;
|
||||
|
||||
template<class K, class V>
|
||||
using hashmap_const_iter = map_wrapper_const_iter<std::unordered_map<K, V>, K, V>;
|
||||
|
25
lib/hashset.h
Normal file
25
lib/hashset.h
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
/* wrapper for std::unordered_set */
|
||||
|
||||
template<class T>
|
||||
class hashset : public set_wrapper<std::unordered_set<T, hasher<T> >, T>
|
||||
{
|
||||
typedef set_wrapper<std::unordered_set<T, hasher<T> >, T> base;
|
||||
|
||||
public:
|
||||
hashset () { }
|
||||
hashset (const hashset &m) : base(m) { }
|
||||
hashset (copy, const hashset &m) : base(COPY, m) { }
|
||||
hashset (initializer_list<T> il) : base(il) { }
|
||||
hashset (reader &r) : base(r) { }
|
||||
~hashset () { }
|
||||
|
||||
hashset &operator = (const hashset &m) { base::operator = (m); return *this; }
|
||||
hashset &operator = (initializer_list<T> il) { base::operator = (il); return *this; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using hashset_iter = set_wrapper_iter<std::unordered_set<T, hasher<T> >, T>;
|
||||
|
||||
template<class T>
|
||||
using hashset_const_iter = set_wrapper_const_iter<std::unordered_set<T, hasher<T> >, T>;
|
380
lib/io.cpp
380
lib/io.cpp
@ -1,10 +1,236 @@
|
||||
|
||||
#include <lib/lib.h>
|
||||
// #include <lib/lib.h>
|
||||
#include <algebra/algebra.h>
|
||||
|
||||
writer::writer (bool raw_)
|
||||
: raw(raw_),
|
||||
aw(new algebra_writer)
|
||||
{
|
||||
}
|
||||
|
||||
writer::~writer ()
|
||||
{
|
||||
delete aw;
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_int (int x)
|
||||
{
|
||||
if (raw)
|
||||
write_raw (&x, sizeof x, 1);
|
||||
else
|
||||
{
|
||||
uint8 buf[5];
|
||||
unsigned n = 0;
|
||||
|
||||
bool more = 1;
|
||||
while (more)
|
||||
{
|
||||
uint8 b = (uint8)(x & 0x7f);
|
||||
x >>= 7;
|
||||
|
||||
if ((x == 0
|
||||
&& ! (b & 0x40))
|
||||
|| (x == -1
|
||||
&& (b & 0x40) == 0x40))
|
||||
more = 0;
|
||||
else
|
||||
b |= 0x80;
|
||||
|
||||
assert (n < 5);
|
||||
buf[n] = b;
|
||||
n ++;
|
||||
}
|
||||
|
||||
write_raw (buf, sizeof buf[0], n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_unsigned (unsigned x)
|
||||
{
|
||||
if (raw)
|
||||
write_raw (&x, sizeof x, 1);
|
||||
else
|
||||
{
|
||||
uint8 buf[5];
|
||||
unsigned n = 0;
|
||||
|
||||
bool more = 1;
|
||||
while (more)
|
||||
{
|
||||
uint8 b = (uint8)(x & 0x7f);
|
||||
x >>= 7;
|
||||
|
||||
if ((x == 0
|
||||
&& ! (b & 0x40)))
|
||||
more = 0;
|
||||
else
|
||||
b |= 0x80;
|
||||
|
||||
assert (n < 5);
|
||||
buf[n] = b;
|
||||
n ++;
|
||||
}
|
||||
|
||||
write_raw (buf, sizeof buf[0], n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_uint64 (uint64 x)
|
||||
{
|
||||
if (raw)
|
||||
write_raw (&x, sizeof x, 1);
|
||||
else
|
||||
{
|
||||
uint8 buf[10];
|
||||
unsigned n = 0;
|
||||
|
||||
bool more = 1;
|
||||
while (more)
|
||||
{
|
||||
uint8 b = (uint8)(x & 0x7f);
|
||||
x >>= 7;
|
||||
|
||||
if ((x == 0
|
||||
&& ! (b & 0x40)))
|
||||
more = 0;
|
||||
else
|
||||
b |= 0x80;
|
||||
|
||||
assert (n < 10);
|
||||
buf[n] = b;
|
||||
n ++;
|
||||
}
|
||||
|
||||
write_raw (buf, sizeof buf[0], n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_mpz (const mpz_t x)
|
||||
{
|
||||
assert (!raw);
|
||||
|
||||
size_t count;
|
||||
void *buf = mpz_export (nullptr, &count, -1, 1, -1, 0, x);
|
||||
|
||||
write_unsigned ((unsigned)count);
|
||||
write_raw (buf, 1, count);
|
||||
|
||||
free (buf);
|
||||
}
|
||||
|
||||
reader::reader (bool raw_)
|
||||
: raw(raw_),
|
||||
ar(new algebra_reader)
|
||||
{
|
||||
}
|
||||
|
||||
reader::~reader ()
|
||||
{
|
||||
delete ar;
|
||||
}
|
||||
|
||||
int
|
||||
reader::read_int ()
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (raw)
|
||||
read_raw (&x, sizeof x, 1);
|
||||
else
|
||||
{
|
||||
int shift = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint8 b = read_uint8 ();
|
||||
x |= ((int)(b & 0x7f) << shift);
|
||||
shift += 7;
|
||||
if (! (b & 0x80))
|
||||
{
|
||||
if (shift < int_bits
|
||||
&& (b & 0x40))
|
||||
x = (x << (int_bits - shift)) >> (int_bits - shift);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned
|
||||
reader::read_unsigned ()
|
||||
{
|
||||
unsigned x = 0;
|
||||
|
||||
if (raw)
|
||||
read_raw (&x, sizeof x, 1);
|
||||
else
|
||||
{
|
||||
unsigned shift = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint8 b = read_uint8 ();
|
||||
x |= ((unsigned)(b & 0x7f) << shift);
|
||||
shift += 7;
|
||||
if (! (b & 0x80))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64
|
||||
reader::read_uint64 ()
|
||||
{
|
||||
uint64 x = 0;
|
||||
|
||||
if (raw)
|
||||
read_raw (&x, sizeof x, 1);
|
||||
else
|
||||
{
|
||||
uint64 shift = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint8 b = read_uint8 ();
|
||||
x |= ((uint64)(b & 0x7f) << shift);
|
||||
shift += 7;
|
||||
if (! (b & 0x80))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
reader::read_mpz (mpz_t x)
|
||||
{
|
||||
assert (!raw);
|
||||
|
||||
unsigned count = read_unsigned ();
|
||||
void *p = malloc (count);
|
||||
if (!p)
|
||||
{
|
||||
stderror ("malloc");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
read_raw (p, 1, count);
|
||||
|
||||
mpz_import (x, count, -1, 1, -1, 0, p);
|
||||
|
||||
free (p);
|
||||
}
|
||||
|
||||
FILE *open_file (const std::string &file, const char *mode)
|
||||
{
|
||||
FILE *fp = fopen (file.c_str (), mode);
|
||||
if (fp == 0)
|
||||
if (!fp)
|
||||
{
|
||||
stderror ("fopen: %s", file.c_str ());
|
||||
exit (EXIT_FAILURE);
|
||||
@ -17,41 +243,32 @@ void close_file (FILE *fp)
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
|
||||
writer::writer (const std::string &file)
|
||||
: fp(0)
|
||||
gzFile
|
||||
open_gzfile (const std::string &file, const char *mode)
|
||||
{
|
||||
fp = open_file (file, "w");
|
||||
}
|
||||
|
||||
writer::~writer ()
|
||||
{
|
||||
if (fp)
|
||||
gzFile gzfp = gzopen (file.c_str (), mode);
|
||||
if (!gzfp)
|
||||
{
|
||||
fclose (fp);
|
||||
fp = 0;
|
||||
stderror ("gzopen: %s", file.c_str ());
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return gzfp;
|
||||
}
|
||||
|
||||
reader::reader (const std::string &file)
|
||||
: fp(0)
|
||||
extern void close_gzfile (gzFile gzfp)
|
||||
{
|
||||
fp = open_file (file, "r");
|
||||
}
|
||||
|
||||
reader::~reader ()
|
||||
{
|
||||
if (fp)
|
||||
int r = gzclose (gzfp);
|
||||
if (r != Z_OK)
|
||||
{
|
||||
fclose (fp);
|
||||
fp = 0;
|
||||
stderror ("gzclose");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_char (char x)
|
||||
file_writer::write_raw (const void *p, size_t itemsize, size_t nitems)
|
||||
{
|
||||
if (fwrite (&x, sizeof x, 1, fp) != 1)
|
||||
if (fwrite (p, itemsize, nitems, fp) != nitems)
|
||||
{
|
||||
stderror ("fwrite");
|
||||
exit (EXIT_FAILURE);
|
||||
@ -59,103 +276,47 @@ writer::write_char (char x)
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_bool (bool x)
|
||||
file_writer::write_mpz (const mpz_t x)
|
||||
{
|
||||
if (fwrite (&x, sizeof x, 1, fp) != 1)
|
||||
mpz_out_raw (fp, x);
|
||||
}
|
||||
|
||||
void
|
||||
file_reader::read_raw (void *p, size_t itemsize, size_t nitems)
|
||||
{
|
||||
if (fread (p, itemsize, nitems, fp) != nitems)
|
||||
{
|
||||
stderror ("fwrite");
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_int (int x)
|
||||
file_reader::read_mpz (mpz_t x)
|
||||
{
|
||||
if (fwrite (&x, sizeof x, 1, fp) != 1)
|
||||
mpz_inp_raw (x, fp);
|
||||
}
|
||||
|
||||
void
|
||||
gzfile_writer::write_raw (const void *p, size_t itemsize, size_t nitems)
|
||||
{
|
||||
unsigned nbytes = itemsize*nitems;
|
||||
if (gzwrite (gzfp, p, nbytes) != nbytes)
|
||||
{
|
||||
stderror ("fwrite");
|
||||
stderror ("gzwrite");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_unsigned (unsigned x)
|
||||
gzfile_reader::read_raw (void *p, size_t itemsize, size_t nitems)
|
||||
{
|
||||
if (fwrite (&x, sizeof x, 1, fp) != 1)
|
||||
{
|
||||
stderror ("fwrite");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writer::write_uint64 (uint64 x)
|
||||
{
|
||||
if (fwrite (&x, sizeof x, 1, fp) != 1)
|
||||
{
|
||||
stderror ("fwrite");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
reader::read_bool ()
|
||||
{
|
||||
bool x;
|
||||
if (fread (&x, sizeof x, 1, fp) != 1)
|
||||
unsigned nbytes = itemsize*nitems;
|
||||
if (gzread (gzfp, p, nbytes) != nitems)
|
||||
{
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
char
|
||||
reader::read_char ()
|
||||
{
|
||||
char x;
|
||||
if (fread (&x, sizeof x, 1, fp) != 1)
|
||||
{
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
reader::read_int ()
|
||||
{
|
||||
int x;
|
||||
if (fread (&x, sizeof x, 1, fp) != 1)
|
||||
{
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned
|
||||
reader::read_unsigned ()
|
||||
{
|
||||
unsigned x;
|
||||
if (fread (&x, sizeof x, 1, fp) != 1)
|
||||
{
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64
|
||||
reader::read_uint64 ()
|
||||
{
|
||||
uint64 x;
|
||||
if (fread (&x, sizeof x, 1, fp) != 1)
|
||||
{
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
@ -164,12 +325,7 @@ read (reader &r, std::string &s)
|
||||
unsigned n = r.read_unsigned ();
|
||||
|
||||
char buf[n + 1];
|
||||
unsigned k = fread (buf, sizeof (char), n + 1, r.fp);
|
||||
if (k != n + 1)
|
||||
{
|
||||
stderror ("fread");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
r.read_raw (buf, sizeof (char), n + 1);
|
||||
assert (buf[n] == 0);
|
||||
|
||||
s = std::string (buf);
|
||||
@ -181,9 +337,5 @@ write (writer &w, const std::string &s)
|
||||
unsigned n = s.length ();
|
||||
w.write_unsigned (n);
|
||||
|
||||
if (fwrite (s.c_str (), sizeof (char), n + 1, w.fp) != n + 1)
|
||||
{
|
||||
stderror ("fwrite");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
w.write_raw (s.c_str (), sizeof (char), n + 1);
|
||||
}
|
||||
|
161
lib/io.h
161
lib/io.h
@ -1,43 +1,162 @@
|
||||
|
||||
extern FILE *open_file (const std::string &file, const char *mode);
|
||||
extern void close_file (FILE *fp);
|
||||
template<class R> class module;
|
||||
|
||||
class algebra_writer;
|
||||
class algebra_reader;
|
||||
|
||||
class writer
|
||||
{
|
||||
public:
|
||||
FILE *fp;
|
||||
bool raw;
|
||||
algebra_writer *aw;
|
||||
|
||||
public:
|
||||
writer (const std::string &file);
|
||||
writer (const writer &); // doesn't exist
|
||||
~writer ();
|
||||
writer (const writer &) = delete;
|
||||
writer (bool raw_);
|
||||
virtual ~writer ();
|
||||
|
||||
writer &operator = (const writer &); // doesn't exist
|
||||
writer &operator = (const writer &) = delete;
|
||||
|
||||
void write_bool (bool x);
|
||||
void write_char (char x);
|
||||
virtual void write_raw (const void *p, size_t itemsize, size_t nitems) = 0;
|
||||
|
||||
void write_bool (bool x) { write_raw (&x, sizeof x, 1); }
|
||||
void write_char (char x) { write_raw (&x, sizeof x, 1); }
|
||||
void write_uint8 (uint8 x) { write_raw (&x, sizeof x, 1); }
|
||||
void write_int (int x);
|
||||
void write_unsigned (unsigned x);
|
||||
void write_uint64 (uint64 x);
|
||||
|
||||
virtual void write_mpz (const mpz_t x);
|
||||
|
||||
template<class R> void write_mod (ptr<const module<R> > m);
|
||||
};
|
||||
|
||||
class reader
|
||||
{
|
||||
public:
|
||||
FILE *fp;
|
||||
|
||||
public:
|
||||
reader (const std::string &file);
|
||||
reader (const reader &); // doesn't exist
|
||||
~reader ();
|
||||
bool raw;
|
||||
algebra_reader *ar;
|
||||
|
||||
reader &operator = (const reader &); // doesn't exist
|
||||
public:
|
||||
reader (const reader &) = delete;
|
||||
reader (bool raw_);
|
||||
virtual ~reader ();
|
||||
|
||||
reader &operator = (const reader &) = delete;
|
||||
|
||||
virtual void read_raw (void *p, size_t itemsize, size_t nitems) = 0;
|
||||
|
||||
bool read_bool ()
|
||||
{
|
||||
bool x;
|
||||
read_raw (&x, sizeof x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
char read_char ()
|
||||
{
|
||||
char x;
|
||||
read_raw (&x, sizeof x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 read_uint8 ()
|
||||
{
|
||||
uint8 x;
|
||||
read_raw (&x, sizeof x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
bool read_bool ();
|
||||
char read_char ();
|
||||
int read_int ();
|
||||
unsigned read_unsigned ();
|
||||
uint64 read_uint64 ();
|
||||
|
||||
virtual void read_mpz (mpz_t x);
|
||||
|
||||
template<class R> ptr<const module<R> > read_mod ();
|
||||
};
|
||||
|
||||
extern FILE *open_file (const std::string &file, const char *mode);
|
||||
extern void close_file (FILE *fp);
|
||||
|
||||
extern gzFile open_gzfile (const std::string &file, const char *mode);
|
||||
extern void close_gzfile (gzFile fp);
|
||||
|
||||
class file_writer : public writer
|
||||
{
|
||||
public:
|
||||
FILE *fp;
|
||||
|
||||
public:
|
||||
file_writer (const std::string &file, bool raw = false)
|
||||
: writer(raw),
|
||||
fp(open_file (file, "w"))
|
||||
{
|
||||
}
|
||||
file_writer (const file_writer &) = delete;
|
||||
~file_writer () { close_file (fp); }
|
||||
|
||||
file_writer &operator = (const file_writer &) = delete;
|
||||
|
||||
void write_raw (const void *p, size_t itemsize, size_t nitems);
|
||||
void write_mpz (const mpz_t x);
|
||||
};
|
||||
|
||||
class file_reader : public reader
|
||||
{
|
||||
public:
|
||||
FILE *fp;
|
||||
|
||||
public:
|
||||
file_reader (const std::string &file, bool raw = false)
|
||||
: reader(raw),
|
||||
fp(open_file (file, "r"))
|
||||
{
|
||||
}
|
||||
file_reader (const file_reader &) = delete;
|
||||
~file_reader () { close_file (fp); }
|
||||
|
||||
file_reader &operator = (const file_reader &) = delete;
|
||||
|
||||
void read_raw (void *p, size_t itemsize, size_t nitems);
|
||||
void read_mpz (mpz_t x);
|
||||
};
|
||||
|
||||
class gzfile_writer : public writer
|
||||
{
|
||||
public:
|
||||
gzFile gzfp;
|
||||
|
||||
public:
|
||||
gzfile_writer (const std::string &file)
|
||||
: writer(false),
|
||||
gzfp(open_gzfile (file, "w9"))
|
||||
{
|
||||
}
|
||||
gzfile_writer (const gzfile_writer &) = delete;
|
||||
~gzfile_writer () { close_gzfile (gzfp); }
|
||||
|
||||
gzfile_writer &operator = (const gzfile_writer &) = delete;
|
||||
|
||||
void write_raw (const void *p, size_t itemsize, size_t nitems);
|
||||
};
|
||||
|
||||
class gzfile_reader : public reader
|
||||
{
|
||||
public:
|
||||
gzFile gzfp;
|
||||
|
||||
public:
|
||||
gzfile_reader (const std::string &file)
|
||||
: reader(false),
|
||||
gzfp(open_gzfile (file, "r"))
|
||||
{
|
||||
}
|
||||
gzfile_reader (const gzfile_reader &) = delete;
|
||||
~gzfile_reader () { close_gzfile (gzfp); }
|
||||
|
||||
gzfile_reader &operator = (const gzfile_reader &) = delete;
|
||||
|
||||
void read_raw (void *p, size_t itemsize, size_t nitems);
|
||||
};
|
||||
|
||||
inline void read (reader &r, bool &x) { x = r.read_bool (); }
|
||||
@ -45,7 +164,7 @@ inline void read (reader &r, char &x) { x = r.read_char (); }
|
||||
inline void read (reader &r, int &x) { x = r.read_int (); }
|
||||
inline void read (reader &r, unsigned &x) { x = r.read_unsigned (); }
|
||||
inline void read (reader &r, uint64 &x) { x = r.read_uint64 (); }
|
||||
void read (reader &r, std::string &s);
|
||||
extern void read (reader &r, std::string &s);
|
||||
template<class T> inline void read (reader &r, T &x) { x = T(r); }
|
||||
|
||||
inline void ctor_read (reader &r, bool *p) { *p = r.read_bool (); }
|
||||
@ -60,5 +179,5 @@ inline void write (writer &w, char x) { w.write_char (x); }
|
||||
inline void write (writer &w, int x) { w.write_int (x); }
|
||||
inline void write (writer &w, unsigned x) { w.write_unsigned (x); }
|
||||
inline void write (writer &w, uint64 x) { w.write_uint64 (x); }
|
||||
void write (writer &w, const std::string &s);
|
||||
extern void write (writer &w, const std::string &s);
|
||||
template<class T> inline void write (writer &w, const T &x) { x.write_self (w); }
|
||||
|
63
lib/lib.h
63
lib/lib.h
@ -1,5 +1,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
@ -7,17 +8,21 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <gmp.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
|
||||
#include <tr1/functional>
|
||||
#include <tr1/unordered_map>
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
/* just need to implement ==, < */
|
||||
template<class T> bool operator != (const T &a, const T &b) { return ! (a == b); }
|
||||
template<class T> bool operator <= (const T &a, const T &b) { return (a < b) || (a == b); }
|
||||
template<class T> bool operator > (const T &a, const T &b) { return ! (a <= b); }
|
||||
template<class T> bool operator >= (const T &a, const T &b) { return ! (a < b); }
|
||||
@ -25,6 +30,8 @@ template<class T> bool operator >= (const T &a, const T &b) { return ! (a < b);
|
||||
typedef enum copy { COPY, COPY1 } copy;
|
||||
typedef enum copy2 { COPY2 } copy2;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
@ -33,8 +40,15 @@ typedef unsigned long ulong;
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
inline int64 abs64 (int64 x) { return llabs (x); }
|
||||
|
||||
typedef size_t hash_t;
|
||||
|
||||
static const unsigned uint8_bits = 8;
|
||||
static const unsigned char_bits = 8;
|
||||
static const unsigned uchar_bits = 8;
|
||||
static const unsigned int_bits = 32;
|
||||
|
||||
inline hash_t hash (bool x) { return (hash_t)x; }
|
||||
inline hash_t hash (char x) { return (hash_t)x; }
|
||||
inline hash_t hash (unsigned char x) { return (hash_t)x; }
|
||||
@ -147,13 +161,24 @@ void stderror (const char *fmt, ...);
|
||||
|
||||
int alpha_to_int (char c);
|
||||
|
||||
#include <lib/io.h>
|
||||
using std::tuple;
|
||||
using std::get;
|
||||
using std::make_tuple;
|
||||
using std::tie;
|
||||
using std::ignore;
|
||||
using std::initializer_list;
|
||||
|
||||
#include <lib/show.h>
|
||||
#include <lib/refcount.h>
|
||||
|
||||
#include <lib/io.h>
|
||||
|
||||
#include <lib/pair.h>
|
||||
|
||||
#include <lib/maybe.h>
|
||||
#include <lib/vector.h>
|
||||
|
||||
#include <lib/set_wrapper.h>
|
||||
#include <lib/set.h>
|
||||
|
||||
class bitset;
|
||||
@ -172,12 +197,40 @@ inline int random_int (int from, int to)
|
||||
#include <lib/bitset.h>
|
||||
#include <lib/ullmanset.h>
|
||||
#include <lib/setcommon.h>
|
||||
|
||||
#include <lib/map_wrapper.h>
|
||||
#include <lib/map.h>
|
||||
|
||||
template<class K>
|
||||
struct hasher : public std::unary_function<K, hash_t>
|
||||
{
|
||||
hash_t operator () (const K &k) const { return hash (k); }
|
||||
};
|
||||
|
||||
#include <lib/hashmap.h>
|
||||
#include <lib/hashset.h>
|
||||
|
||||
#include <lib/ullmanmap.h>
|
||||
#include <lib/mapcommon.h>
|
||||
#include <lib/unionfind.h>
|
||||
#include <lib/priority_queue.h>
|
||||
#include <lib/directed_multigraph.h>
|
||||
|
||||
// ??? io
|
||||
|
||||
class algebra_writer
|
||||
{
|
||||
public:
|
||||
// modules
|
||||
unsigned io_id_counter;
|
||||
map<unsigned, unsigned> id_io_id;
|
||||
|
||||
algebra_writer () : io_id_counter(0) { }
|
||||
~algebra_writer () { }
|
||||
};
|
||||
|
||||
class algebra_reader
|
||||
{
|
||||
public:
|
||||
map<unsigned, unsigned> io_id_id;
|
||||
|
||||
};
|
||||
|
15
lib/map.h
15
lib/map.h
@ -1,5 +1,5 @@
|
||||
|
||||
/* wrapper for stl map */
|
||||
/* wrapper for std::map */
|
||||
|
||||
template<class K, class V>
|
||||
class map : public map_wrapper<std::map<K, V>, K, V>
|
||||
@ -11,9 +11,20 @@ class map : public map_wrapper<std::map<K, V>, K, V>
|
||||
map (unsigned dummy_size) : base(dummy_size) { }
|
||||
map (const map &m) : base(m) { }
|
||||
map (copy, const map &m) : base(COPY, m) { }
|
||||
map (copy2, const map &m) : base(COPY2, m) { }
|
||||
map (initializer_list<std::pair<const K, V> > il) : base(il) { }
|
||||
map (reader &r) : base(r) { }
|
||||
~map () { }
|
||||
|
||||
map &operator = (const map &m) { base::operator = (m); return *this; }
|
||||
map &operator = (initializer_list<std::pair<const K, V> > il)
|
||||
{
|
||||
base::operator = (il);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class K, class V>
|
||||
using map_iter = map_wrapper_iter<std::map<K, V>, K, V>;
|
||||
|
||||
template<class K, class V>
|
||||
using map_const_iter = map_wrapper_const_iter<std::map<K, V>, K, V>;
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
/* wrapper for stl maps */
|
||||
/* wrapper for STL maps */
|
||||
|
||||
template<class M, class K, class V> class map_wrapper_iter;
|
||||
template<class M, class K, class V> class map_wrapper_const_iter;
|
||||
@ -7,14 +7,23 @@ template<class M, class K, class V> class map_wrapper_const_iter;
|
||||
template<class M, class K, class V>
|
||||
class map_wrapper
|
||||
{
|
||||
private:
|
||||
friend class map_wrapper_iter<M, K, V>;
|
||||
friend class map_wrapper_const_iter<M, K, V>;
|
||||
|
||||
|
||||
protected:
|
||||
class map_impl : public refcounted
|
||||
{
|
||||
public:
|
||||
M t;
|
||||
|
||||
public:
|
||||
map_impl () = default;
|
||||
map_impl (const map_impl &) = delete;
|
||||
map_impl (const M &t_) : t(t_) { }
|
||||
map_impl (initializer_list<std::pair<const K, V> > il) : t(il) { }
|
||||
~map_impl () = default;
|
||||
|
||||
map_impl &operator = (const map_impl &) = delete;
|
||||
};
|
||||
|
||||
ptr<map_impl> impl;
|
||||
@ -25,14 +34,24 @@ class map_wrapper
|
||||
|
||||
public:
|
||||
map_wrapper () : impl(new map_impl) { }
|
||||
map_wrapper (unsigned dummy_size) : impl(new map_impl) { }
|
||||
map_wrapper (const map_wrapper &m) : impl(m.impl) { }
|
||||
map_wrapper (copy, const map_wrapper &m) : impl(new map_impl) { impl->t = M (m.impl->t); }
|
||||
map_wrapper (copy2, const map_wrapper &m);
|
||||
map_wrapper (copy, const map_wrapper &m) : impl(new map_impl (m.impl->t)) { }
|
||||
map_wrapper (initializer_list<std::pair<const K, V> > il)
|
||||
: impl(new map_impl (il))
|
||||
{ }
|
||||
map_wrapper (reader &r);
|
||||
~map_wrapper () { }
|
||||
|
||||
map_wrapper &operator = (const map_wrapper &m) { impl = m.impl; return *this; }
|
||||
map_wrapper &operator = (initializer_list<std::pair<const K, V> > il)
|
||||
{
|
||||
impl->t = il;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// range-based for
|
||||
typename M::const_iterator begin () const { return impl->t.begin (); }
|
||||
typename M::const_iterator end () const { return impl->t.end (); }
|
||||
|
||||
/* returns the pair associated to the smallest key */
|
||||
pair<K, V> head () const
|
||||
@ -130,20 +149,12 @@ class map_wrapper
|
||||
}
|
||||
|
||||
bool operator == (const map_wrapper &m) const;
|
||||
bool operator != (const map_wrapper &m) const { return !operator == (m); }
|
||||
bool operator < (const map_wrapper &m) const;
|
||||
|
||||
void write_self (writer &w) const;
|
||||
};
|
||||
|
||||
template<class M, class K, class V>
|
||||
map_wrapper<M, K, V>::map_wrapper (copy2, const map_wrapper &m)
|
||||
: impl(new map_impl)
|
||||
{
|
||||
/* Keys are immutable. Just copy the values. */
|
||||
for (const_iter i = m; i; i ++)
|
||||
push (i.key (), V (COPY, i.val ()));
|
||||
}
|
||||
|
||||
template<class M, class K, class V>
|
||||
map_wrapper<M, K, V>::map_wrapper (reader &r)
|
||||
: impl(new map_impl)
|
||||
@ -222,19 +233,19 @@ template<class M, class K, class V>
|
||||
class map_wrapper_iter
|
||||
{
|
||||
private:
|
||||
map_wrapper<M, K, V> &m;
|
||||
ptr<typename map_wrapper<M, K, V>::map_impl> impl;
|
||||
typename M::iterator i, end;
|
||||
bool deleted;
|
||||
|
||||
public:
|
||||
map_wrapper_iter (map_wrapper<M, K, V> &m_) : m(m_), i(m_.impl->t.begin ()), end(m_.impl->t.end ()), deleted(0) { }
|
||||
map_wrapper_iter (map_wrapper<M, K, V> &m) : impl(m.impl), i(m.impl->t.begin ()), end(m.impl->t.end ()), deleted(0) { }
|
||||
~map_wrapper_iter () { }
|
||||
|
||||
void del ()
|
||||
{
|
||||
assert (!deleted);
|
||||
typename M::iterator iprev = i ++;
|
||||
m.impl->t.erase (iprev);
|
||||
impl->t.erase (iprev);
|
||||
deleted = 1;
|
||||
}
|
||||
|
||||
@ -249,10 +260,11 @@ template<class M, class K, class V>
|
||||
class map_wrapper_const_iter
|
||||
{
|
||||
private:
|
||||
ptr<const typename map_wrapper<M, K, V>::map_impl> impl;
|
||||
typename M::const_iterator i, end;
|
||||
|
||||
public:
|
||||
map_wrapper_const_iter (const map_wrapper<M, K, V> &m) : i(m.impl->t.begin ()), end(m.impl->t.end ()) { }
|
||||
map_wrapper_const_iter (const map_wrapper<M, K, V> &m) : impl(m.impl), i(m.impl->t.begin ()), end(m.impl->t.end ()) { }
|
||||
~map_wrapper_const_iter () { }
|
||||
|
||||
const K &key () const { return i->first; }
|
||||
|
30
lib/pair.h
30
lib/pair.h
@ -17,6 +17,7 @@ class pair
|
||||
pair &operator = (const pair &p) { first = p.first; second = p.second; return *this; }
|
||||
|
||||
bool operator == (const pair &p) const { return first == p.first && second == p.second; }
|
||||
bool operator != (const pair &p) const { return !operator == (p); }
|
||||
bool operator < (const pair &p) const { return (first < p.first
|
||||
|| (first == p.first && second < p.second)); }
|
||||
|
||||
@ -53,8 +54,9 @@ public:
|
||||
triple (const F &first_, const S &second_, const T &third_)
|
||||
: first(first_), second(second_), third(third_)
|
||||
{ }
|
||||
triple (reader &r);
|
||||
~triple () { }
|
||||
|
||||
|
||||
triple &operator = (const triple &t)
|
||||
{
|
||||
first = t.first;
|
||||
@ -67,6 +69,8 @@ public:
|
||||
{
|
||||
return first == t.first && second == t.second && third == t.third;
|
||||
}
|
||||
bool operator != (const triple &t) const { return !operator == (t); }
|
||||
|
||||
bool operator < (const triple &t) const
|
||||
{
|
||||
if (first < t.first)
|
||||
@ -78,13 +82,11 @@ public:
|
||||
return 1;
|
||||
else if (second > t.second)
|
||||
return 0;
|
||||
|
||||
if (third < t.third)
|
||||
return 1;
|
||||
else if (third > t.third)
|
||||
return 0;
|
||||
|
||||
return third < t.third;
|
||||
}
|
||||
|
||||
void write_self (writer &w) const;
|
||||
hash_t hash_self () const
|
||||
{
|
||||
hash_t h = hash (first);
|
||||
@ -92,3 +94,19 @@ public:
|
||||
return hash_combine (h, hash (third));
|
||||
}
|
||||
};
|
||||
|
||||
template <class F, class S, class T>
|
||||
triple<F, S, T>::triple (reader &r)
|
||||
{
|
||||
read (r, first);
|
||||
read (r, second);
|
||||
read (r, third);
|
||||
}
|
||||
|
||||
template<class F, class S, class T> void
|
||||
triple<F, S, T>::write_self (writer &w) const
|
||||
{
|
||||
write (w, first);
|
||||
write (w, second);
|
||||
write (w, third);
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ class priority_queue
|
||||
weighted &operator = (const weighted &w) { v = w.v; pri = w.pri; }
|
||||
|
||||
bool operator == (const weighted &w) const { return v == w.v && pri == w.pri; }
|
||||
bool operator != (const weighted &w) const { return !operator == (w); }
|
||||
|
||||
bool operator < (const weighted &w) const { return pri > w.pri || (pri == w.pri && v < w.v); }
|
||||
};
|
||||
|
||||
|
@ -42,10 +42,10 @@ class refcounted
|
||||
|
||||
public:
|
||||
refcounted () : refcount(0) { }
|
||||
refcounted (const refcounted &rc); // doesn't exist
|
||||
refcounted (const refcounted &rc) = delete;
|
||||
~refcounted () { }
|
||||
|
||||
refcounted &operator = (const refcounted &rc); // doesn't exist
|
||||
refcounted &operator = (const refcounted &rc) = delete;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
219
lib/set.h
219
lib/set.h
@ -1,149 +1,46 @@
|
||||
|
||||
/* wrap for std::set */
|
||||
|
||||
template<class T> class set_iter;
|
||||
template<class T> class set_const_iter;
|
||||
/* wrapper for std::set */
|
||||
|
||||
template<class T>
|
||||
class set
|
||||
class set : public set_wrapper<std::set<T>, T>
|
||||
{
|
||||
private:
|
||||
friend class set_iter<T>;
|
||||
friend class set_const_iter<T>;
|
||||
|
||||
class set_impl : public refcounted
|
||||
{
|
||||
public:
|
||||
std::set<T> t;
|
||||
};
|
||||
|
||||
ptr<set_impl> impl;
|
||||
typedef set_wrapper<std::set<T>, T> base;
|
||||
|
||||
public:
|
||||
typedef set_iter<T> iter;
|
||||
typedef set_const_iter<T> const_iter;
|
||||
|
||||
public:
|
||||
set () : impl(new set_impl) { }
|
||||
set (unsigned dummy_size) : impl(new set_impl) { }
|
||||
set (const set &s) : impl(s.impl) { }
|
||||
set (copy, const set &s) : impl(new set_impl) { impl->t = std::set<T> (s.impl->t); }
|
||||
set (reader &r);
|
||||
set () { }
|
||||
set (const set &m) : base(m) { }
|
||||
set (copy, const set &m) : base(COPY, m) { }
|
||||
set (initializer_list<T> il) : base(il) { }
|
||||
set (reader &r) : base(r) { }
|
||||
~set () { }
|
||||
|
||||
set &operator = (const set &s) { impl = s.impl; return *this; }
|
||||
|
||||
T pop ()
|
||||
{
|
||||
typename std::set<T>::const_iterator i = impl->t.begin ();
|
||||
assert (i != impl->t.end ());
|
||||
T tmp = *i;
|
||||
impl->t.erase (i);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool is_empty () const { return impl->t.empty (); }
|
||||
unsigned card () const { return impl->t.size (); }
|
||||
const T &head () const;
|
||||
const T &tail () const;
|
||||
set &operator = (const set &m) { base::operator = (m); return *this; }
|
||||
set &operator = (initializer_list<T> il) { base::operator = (il); }
|
||||
|
||||
bool operator == (const set &s) const;
|
||||
bool operator != (const set &s) const { return !operator == (s); }
|
||||
bool operator < (const set &s) const;
|
||||
bool operator <= (const set &s) const;
|
||||
|
||||
void clear () { impl->t.clear (); }
|
||||
void push (const T &v) { assert (impl->t.find (v) == impl->t.end ()); impl->t.insert (v); }
|
||||
bool toggle (const T &v);
|
||||
void operator += (const T &v) { impl->t.insert (v); }
|
||||
void operator -= (const T &v) { impl->t.erase (v); }
|
||||
void yank (const T &v) { assert (operator % (v)); impl->t.erase (v); }
|
||||
|
||||
set &operator |= (const set<T> &s);
|
||||
set &operator &= (const set<T> &s);
|
||||
set &operator ^= (const set<T> &s);
|
||||
|
||||
bool operator % (const T &v) const { return impl->t.find (v) != impl->t.end (); }
|
||||
bool operator () (const T &v) const { return operator % (v); }
|
||||
|
||||
void write_self (writer &w) const;
|
||||
hash_t hash_self () const;
|
||||
set &operator |= (const set &s);
|
||||
set &operator &= (const set &s);
|
||||
set &operator ^= (const set &s);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class set_iter
|
||||
{
|
||||
set<T> &s;
|
||||
typename std::set<T>::const_iterator i, end;
|
||||
bool deleted;
|
||||
|
||||
public:
|
||||
set_iter (set<T> &s_) : s(s_), i(s_.impl->t.begin ()), end(s_.impl->t.end ()), deleted(0) { }
|
||||
~set_iter () { }
|
||||
|
||||
void del ()
|
||||
{
|
||||
assert (!deleted);
|
||||
typename std::set<T>::const_iterator iprev = i ++;
|
||||
s.impl->t.erase (iprev);
|
||||
deleted = 1;
|
||||
}
|
||||
|
||||
const T &val () const { assert (!deleted); return *i; }
|
||||
operator bool () const { assert (!deleted); return i != end; }
|
||||
set_iter &operator ++ () { if (deleted) deleted = 0; else i ++; return *this; }
|
||||
void operator ++ (int) { operator ++ (); }
|
||||
};
|
||||
using set_iter = set_wrapper_iter<std::set<T>, T>;
|
||||
|
||||
template<class T>
|
||||
class set_const_iter
|
||||
{
|
||||
typename std::set<T>::const_iterator i, end;
|
||||
|
||||
public:
|
||||
set_const_iter (const set<T> &s) : i(s.impl->t.begin ()), end(s.impl->t.end ()) { }
|
||||
~set_const_iter () { }
|
||||
|
||||
const T &val () const { return *i; }
|
||||
operator bool () const { return i != end; }
|
||||
set_const_iter &operator ++ () { i ++; return *this; }
|
||||
void operator ++ (int) { i ++; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
set<T>::set (reader &r)
|
||||
{
|
||||
unsigned n;
|
||||
read (r, n);
|
||||
T x;
|
||||
for (unsigned i = 0; i < n; i ++)
|
||||
{
|
||||
read (r, x);
|
||||
push (x);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> const T &
|
||||
set<T>::head () const
|
||||
{
|
||||
set_const_iter<T> i = *this;
|
||||
assert (i);
|
||||
return i.val ();
|
||||
}
|
||||
|
||||
template<class T> const T &
|
||||
set<T>::tail () const
|
||||
{
|
||||
typename std::set<T>::const_reverse_iterator i = impl->t.rbegin ();
|
||||
assert (i != impl->t.rend ());
|
||||
return *i;
|
||||
}
|
||||
using set_const_iter = set_wrapper_const_iter<std::set<T>, T>;
|
||||
|
||||
template<class T> bool
|
||||
set<T>::operator == (const set &s) const
|
||||
{
|
||||
typename std::set<T>::const_iterator i = impl->t.begin (),
|
||||
typename std::set<T>::const_iterator i = this->impl->t.begin (),
|
||||
j = s.impl->t.begin (),
|
||||
iend = impl->t.end (),
|
||||
iend = this->impl->t.end (),
|
||||
jend = s.impl->t.end ();
|
||||
|
||||
while (i != iend && j != jend && *i == *j)
|
||||
@ -155,9 +52,9 @@ set<T>::operator == (const set &s) const
|
||||
template<class T> bool
|
||||
set<T>::operator < (const set &s) const
|
||||
{
|
||||
typename std::set<T>::const_iterator i = impl->t.begin (),
|
||||
typename std::set<T>::const_iterator i = this->impl->t.begin (),
|
||||
j = s.impl->t.begin (),
|
||||
iend = impl->t.end (),
|
||||
iend = this->impl->t.end (),
|
||||
jend = s.impl->t.end ();
|
||||
|
||||
while (i != iend && j != jend && *i == *j)
|
||||
@ -169,9 +66,9 @@ set<T>::operator < (const set &s) const
|
||||
template<class T> bool
|
||||
set<T>::operator <= (const set &s) const
|
||||
{
|
||||
typename std::set<T>::const_iterator i = impl->t.begin (),
|
||||
typename std::set<T>::const_iterator i = this->impl->t.begin (),
|
||||
j = s.impl->t.begin (),
|
||||
iend = impl->t.end (),
|
||||
iend = this->impl->t.end (),
|
||||
jend = s.impl->t.end ();
|
||||
|
||||
while (i != iend && j != jend && *i == *j)
|
||||
@ -184,56 +81,56 @@ set<T>::operator <= (const set &s) const
|
||||
template<class T> bool
|
||||
set<T>::toggle (const T &v)
|
||||
{
|
||||
typename std::set<T>::const_iterator i = impl->t.lower_bound (v),
|
||||
end = impl->t.end ();
|
||||
typename std::set<T>::const_iterator i = this->impl->t.lower_bound (v),
|
||||
end = this->impl->t.end ();
|
||||
if (i != end && *i == v)
|
||||
{
|
||||
impl->t.erase (i);
|
||||
this->impl->t.erase (i);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i == impl->t.begin ())
|
||||
impl->t.insert (v);
|
||||
if (i == this->impl->t.begin ())
|
||||
this->impl->t.insert (v);
|
||||
else
|
||||
{
|
||||
typename std::set<T>::const_iterator j = --i;
|
||||
assert (*j < v);
|
||||
impl->t.insert (j, v);
|
||||
this->impl->t.insert (j, v);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> set<T> &
|
||||
set<T>::operator |= (const set<T> &s)
|
||||
set<T>::operator |= (const set &s)
|
||||
{
|
||||
std::set<T> news;
|
||||
std::set_union (impl->t.begin (), impl->t.end (),
|
||||
std::set_union (this->impl->t.begin (), this->impl->t.end (),
|
||||
s.impl->t.begin (), s.impl->t.end (),
|
||||
inserter (news, news.begin ()));
|
||||
impl->t = news;
|
||||
this->impl->t = news;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> set<T> &
|
||||
set<T>::operator &= (const set<T> &s)
|
||||
set<T>::operator &= (const set &s)
|
||||
{
|
||||
std::set<T> news;
|
||||
std::set_intersection (impl->t.begin (), impl->t.end (),
|
||||
std::set_intersection (this->impl->t.begin (), this->impl->t.end (),
|
||||
s.impl->t.begin (), s.impl->t.end (),
|
||||
inserter (news, news.begin ()));
|
||||
impl->t = news;
|
||||
this->impl->t = news;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> set<T> &
|
||||
set<T>::operator ^= (const set<T> &s)
|
||||
set<T>::operator ^= (const set &s)
|
||||
{
|
||||
#if 0
|
||||
printf ("before:\n");
|
||||
printf ("this:");
|
||||
for (typename std::set<T>::const_iterator i = impl->t.begin (); i != impl->t.end (); i ++)
|
||||
for (typename std::set<T>::const_iterator i = this->impl->t.begin (); i != this->impl->t.end (); i ++)
|
||||
printf (" %d", *i);
|
||||
printf ("\n");
|
||||
printf ("s:");
|
||||
@ -243,25 +140,25 @@ set<T>::operator ^= (const set<T> &s)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
typename std::set<T>::const_iterator i = impl->t.begin (),
|
||||
iend = impl->t.end (),
|
||||
typename std::set<T>::const_iterator i = this->impl->t.begin (),
|
||||
iend = this->impl->t.end (),
|
||||
j = s.impl->t.begin (),
|
||||
jend = s.impl->t.end ();
|
||||
|
||||
while (i != iend && j != jend && *i == *j)
|
||||
{
|
||||
impl->t.erase (i);
|
||||
i = impl->t.begin ();
|
||||
this->impl->t.erase (i);
|
||||
i = this->impl->t.begin ();
|
||||
j ++;
|
||||
}
|
||||
|
||||
if (i == iend)
|
||||
impl->t.insert (j, jend);
|
||||
this->impl->t.insert (j, jend);
|
||||
else
|
||||
{
|
||||
if (j != jend && *j < *i)
|
||||
{
|
||||
i = impl->t.insert (*j).first;
|
||||
i = this->impl->t.insert (*j).first;
|
||||
j ++;
|
||||
}
|
||||
|
||||
@ -274,14 +171,14 @@ set<T>::operator ^= (const set<T> &s)
|
||||
{
|
||||
while (j != jend)
|
||||
{
|
||||
iprev = impl->t.insert (iprev, *j);
|
||||
iprev = this->impl->t.insert (iprev, *j);
|
||||
j ++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (*i == *j)
|
||||
{
|
||||
impl->t.erase (i);
|
||||
this->impl->t.erase (i);
|
||||
i = iprev;
|
||||
j ++;
|
||||
}
|
||||
@ -289,12 +186,12 @@ set<T>::operator ^= (const set<T> &s)
|
||||
{
|
||||
while (j != jend && *j < *i)
|
||||
{
|
||||
iprev = impl->t.insert (iprev, *j);
|
||||
iprev = this->impl->t.insert (iprev, *j);
|
||||
j ++;
|
||||
}
|
||||
if (j != jend && *j == *i)
|
||||
{
|
||||
impl->t.erase (i);
|
||||
this->impl->t.erase (i);
|
||||
i = iprev;
|
||||
j ++;
|
||||
}
|
||||
@ -305,37 +202,19 @@ set<T>::operator ^= (const set<T> &s)
|
||||
|
||||
#if 0
|
||||
std::set<T> news;
|
||||
std::set_symmetric_difference (impl->t.begin (), impl->t.end (),
|
||||
std::set_symmetric_difference (this->impl->t.begin (), this->impl->t.end (),
|
||||
s.impl->t.begin (), s.impl->t.end (),
|
||||
inserter (news, news.begin ()));
|
||||
impl->t = news;
|
||||
this->impl->t = news;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printf ("after:\n");
|
||||
printf ("this:");
|
||||
for (typename std::set<T>::const_iterator i = impl->t.begin (); i != impl->t.end (); i ++)
|
||||
for (typename std::set<T>::const_iterator i = this->impl->t.begin (); i != this->impl->t.end (); i ++)
|
||||
printf (" %d", *i);
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> void
|
||||
set<T>::write_self (writer &w) const
|
||||
{
|
||||
write (w, card ());
|
||||
for (const_iter i = *this; i; i ++)
|
||||
write (w, i.val ());
|
||||
}
|
||||
|
||||
template<class T> hash_t
|
||||
set<T>::hash_self () const
|
||||
{
|
||||
hash_t h = hash (card ());
|
||||
unsigned j = 0;
|
||||
for (const_iter i = *this; i && j < 10; i ++, j ++)
|
||||
h = hash_combine (h, hash (i.val ()));
|
||||
return h;
|
||||
}
|
||||
|
171
lib/set_wrapper.h
Normal file
171
lib/set_wrapper.h
Normal file
@ -0,0 +1,171 @@
|
||||
|
||||
/* wrapper for STL maps */
|
||||
|
||||
template<class S, class T> class set_wrapper_iter;
|
||||
template<class S, class T> class set_wrapper_const_iter;
|
||||
|
||||
template<class S, class T>
|
||||
class set_wrapper
|
||||
{
|
||||
friend class set_wrapper_iter<S, T>;
|
||||
friend class set_wrapper_const_iter<S, T>;
|
||||
|
||||
protected:
|
||||
class set_wrapper_impl : public refcounted
|
||||
{
|
||||
public:
|
||||
S t;
|
||||
|
||||
public:
|
||||
set_wrapper_impl () = default;
|
||||
set_wrapper_impl (const set_wrapper_impl &) = delete;
|
||||
set_wrapper_impl (const S &t_) : t(t_) { }
|
||||
set_wrapper_impl (initializer_list<T> il) : t(il) { }
|
||||
~set_wrapper_impl () = default;
|
||||
|
||||
set_wrapper_impl &operator = (const set_wrapper_impl &) = delete;
|
||||
};
|
||||
|
||||
ptr<set_wrapper_impl> impl;
|
||||
|
||||
public:
|
||||
typedef set_wrapper_iter<S, T> iter;
|
||||
typedef set_wrapper_const_iter<S, T> const_iter;
|
||||
|
||||
public:
|
||||
set_wrapper () : impl(new set_wrapper_impl) { }
|
||||
set_wrapper (const set_wrapper &s) : impl(s.impl) { }
|
||||
set_wrapper (copy, const set_wrapper &s)
|
||||
: impl(new set_wrapper_impl (s.impl->t))
|
||||
{ }
|
||||
set_wrapper (initializer_list<T> il)
|
||||
: impl(new set_wrapper_impl (il))
|
||||
{ }
|
||||
set_wrapper (reader &r);
|
||||
~set_wrapper () { }
|
||||
|
||||
set_wrapper &operator = (const set_wrapper &s) { impl = s.impl; return *this; }
|
||||
set_wrapper &operator = (initializer_list<T> li)
|
||||
{
|
||||
impl->t = li;
|
||||
}
|
||||
|
||||
// range-based for
|
||||
typename S::const_iterator begin () const { return impl->t.begin (); }
|
||||
typename S::const_iterator end () const { return impl->t.end (); }
|
||||
|
||||
T pop ()
|
||||
{
|
||||
typename S::const_iterator i = impl->t.begin ();
|
||||
assert (i != impl->t.end ());
|
||||
T tmp = *i;
|
||||
impl->t.erase (i);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool is_empty () const { return impl->t.empty (); }
|
||||
unsigned card () const { return impl->t.size (); }
|
||||
const T &head () const;
|
||||
const T &tail () const;
|
||||
|
||||
void clear () { impl->t.clear (); }
|
||||
void push (const T &v) { assert (impl->t.find (v) == impl->t.end ()); impl->t.insert (v); }
|
||||
void operator += (const T &v) { impl->t.insert (v); }
|
||||
void operator -= (const T &v) { impl->t.erase (v); }
|
||||
void yank (const T &v) { assert (operator % (v)); impl->t.erase (v); }
|
||||
|
||||
bool operator % (const T &v) const { return impl->t.find (v) != impl->t.end (); }
|
||||
bool operator () (const T &v) const { return operator % (v); }
|
||||
|
||||
void write_self (writer &w) const;
|
||||
hash_t hash_self () const;
|
||||
};
|
||||
|
||||
template<class S, class T>
|
||||
class set_wrapper_iter
|
||||
{
|
||||
ptr<typename set_wrapper<S, T>::set_wrapper_impl> impl;
|
||||
typename S::const_iterator i, end;
|
||||
bool deleted;
|
||||
|
||||
public:
|
||||
set_wrapper_iter (set_wrapper<S, T> &s) : impl(s.impl), i(s.impl->t.begin ()), end(s.impl->t.end ()), deleted(0) { }
|
||||
~set_wrapper_iter () { }
|
||||
|
||||
void del ()
|
||||
{
|
||||
assert (!deleted);
|
||||
typename S::const_iterator iprev = i ++;
|
||||
impl->t.erase (iprev);
|
||||
deleted = 1;
|
||||
}
|
||||
|
||||
const T &val () const { assert (!deleted); return *i; }
|
||||
operator bool () const { assert (!deleted); return i != end; }
|
||||
set_wrapper_iter &operator ++ () { if (deleted) deleted = 0; else i ++; return *this; }
|
||||
void operator ++ (int) { operator ++ (); }
|
||||
};
|
||||
|
||||
template<class S, class T>
|
||||
class set_wrapper_const_iter
|
||||
{
|
||||
ptr<const typename set_wrapper<S, T>::set_wrapper_impl> impl;
|
||||
typename S::const_iterator i, end;
|
||||
|
||||
public:
|
||||
set_wrapper_const_iter (const set_wrapper<S, T> &s) : impl(s.impl), i(s.impl->t.begin ()), end(s.impl->t.end ()) { }
|
||||
~set_wrapper_const_iter () { }
|
||||
|
||||
const T &val () const { return *i; }
|
||||
operator bool () const { return i != end; }
|
||||
set_wrapper_const_iter &operator ++ () { i ++; return *this; }
|
||||
void operator ++ (int) { i ++; }
|
||||
};
|
||||
|
||||
template<class S, class T>
|
||||
set_wrapper<S, T>::set_wrapper (reader &r)
|
||||
: impl(new set_wrapper_impl)
|
||||
{
|
||||
unsigned n;
|
||||
read (r, n);
|
||||
T x;
|
||||
for (unsigned i = 0; i < n; i ++)
|
||||
{
|
||||
read (r, x);
|
||||
push (x);
|
||||
}
|
||||
}
|
||||
|
||||
template<class S, class T> const T &
|
||||
set_wrapper<S, T>::head () const
|
||||
{
|
||||
set_wrapper_const_iter<S, T> i = *this;
|
||||
assert (i);
|
||||
return i.val ();
|
||||
}
|
||||
|
||||
template<class S, class T> const T &
|
||||
set_wrapper<S, T>::tail () const
|
||||
{
|
||||
typename S::const_reverse_iterator i = impl->t.rbegin ();
|
||||
assert (i != impl->t.rend ());
|
||||
return *i;
|
||||
}
|
||||
|
||||
template<class S, class T> void
|
||||
set_wrapper<S, T>::write_self (writer &w) const
|
||||
{
|
||||
write (w, card ());
|
||||
for (const_iter i = *this; i; i ++)
|
||||
write (w, i.val ());
|
||||
}
|
||||
|
||||
template<class S, class T> hash_t
|
||||
set_wrapper<S, T>::hash_self () const
|
||||
{
|
||||
hash_t h = hash (card ());
|
||||
unsigned j = 0;
|
||||
for (const_iter i = *this; i && j < 10; i ++, j ++)
|
||||
h = hash_combine (h, hash (i.val ()));
|
||||
return h;
|
||||
}
|
174
lib/ullmanset.h
174
lib/ullmanset.h
@ -2,12 +2,15 @@
|
||||
template<unsigned B> class ullmanset_iter;
|
||||
template<unsigned B> class ullmanset_const_iter;
|
||||
|
||||
template<unsigned B> class ullmanset_const_stl_iter;
|
||||
|
||||
template<unsigned B>
|
||||
class ullmanset
|
||||
{
|
||||
private:
|
||||
friend class ullmanset_iter<B>;
|
||||
friend class ullmanset_const_iter<B>;
|
||||
friend class ullmanset_const_stl_iter<B>;
|
||||
|
||||
class keypos
|
||||
{
|
||||
@ -16,57 +19,56 @@ class ullmanset
|
||||
unsigned pos;
|
||||
};
|
||||
|
||||
class data
|
||||
class data : public refcounted
|
||||
{
|
||||
public:
|
||||
unsigned refcount;
|
||||
unsigned size;
|
||||
unsigned n;
|
||||
keypos kp[1];
|
||||
|
||||
public:
|
||||
inline void delete_at_pos (unsigned p);
|
||||
};
|
||||
|
||||
data *d;
|
||||
|
||||
void ref (data *newd) { assert (!d); d = newd; if (d) d->refcount ++; }
|
||||
void unref ();
|
||||
|
||||
inline void delete_at_pos (unsigned p);
|
||||
ptr<data> d;
|
||||
|
||||
public:
|
||||
typedef ullmanset_iter<B> iter;
|
||||
typedef ullmanset_const_iter<B> const_iter;
|
||||
|
||||
public:
|
||||
ullmanset () : d(0) { }
|
||||
ullmanset (unsigned size);
|
||||
ullmanset (const ullmanset &s) : d(0) { ref (s.d); }
|
||||
ullmanset () : ullmanset(0) { }
|
||||
ullmanset (const ullmanset &s) : d(s.d) { }
|
||||
ullmanset (copy, const ullmanset &s);
|
||||
// ullmanset (const unsignedset &t);
|
||||
ullmanset (const bitset &t);
|
||||
ullmanset (unsigned size, initializer_list<unsigned> il);
|
||||
ullmanset (reader &r);
|
||||
~ullmanset () { unref (); }
|
||||
~ullmanset () { }
|
||||
|
||||
ullmanset &operator = (const ullmanset &s) { unref (); ref (s.d); return *this; }
|
||||
// ullmanset &operator = (const unsignedset &t);
|
||||
ullmanset &operator = (const ullmanset &s) { d = s.d; return *this; }
|
||||
ullmanset &operator = (const bitset &t);
|
||||
|
||||
unsigned size () const { return d ? d->size : 0; }
|
||||
// range-based for
|
||||
inline ullmanset_const_stl_iter<B> begin () const;
|
||||
inline ullmanset_const_stl_iter<B> end () const;
|
||||
|
||||
bool is_empty () const { assert (d); return d->n == 0; }
|
||||
unsigned card () const { assert (d); return d->n; }
|
||||
unsigned head () const { assert (d); assert (d->n > 0); return d->kp[0].key; }
|
||||
unsigned size () const { return d->size; }
|
||||
|
||||
bool is_empty () const { return d->n == 0; }
|
||||
unsigned card () const { return d->n; }
|
||||
unsigned head () const { assert (d->n > 0); return d->kp[0].key; }
|
||||
|
||||
bool operator == (const ullmanset &s);
|
||||
bool operator != (const ullmanset &s) { return !operator == (s); }
|
||||
|
||||
void restore (unsigned old_card)
|
||||
{
|
||||
assert (d);
|
||||
assert (d->n >= old_card);
|
||||
d->n = old_card;
|
||||
}
|
||||
|
||||
void clear () { if (d) { d->n = 0; } }
|
||||
void clear () { d->n = 0; }
|
||||
|
||||
inline void push (unsigned k);
|
||||
inline void operator += (unsigned k); // ??? should these be inline?
|
||||
@ -88,89 +90,75 @@ class ullmanset
|
||||
|
||||
bool operator % (unsigned k) const
|
||||
{
|
||||
assert (d);
|
||||
assert ((k - B) >= 0);
|
||||
assert ((k - B) < d->size);
|
||||
unsigned p = d->kp[k - B].pos;
|
||||
return p < d->n && d->kp[p].key == k;
|
||||
}
|
||||
|
||||
bool operator () (unsigned k) const { return operator % (k); }
|
||||
|
||||
// always 0-based
|
||||
unsigned nth (unsigned p) const { assert (d); assert (p < d->n); return d->kp[p].key; }
|
||||
unsigned nth (unsigned p) const
|
||||
{
|
||||
assert (p < d->n);
|
||||
return d->kp[p].key;
|
||||
}
|
||||
|
||||
unsigned position (unsigned k) const { assert (operator % (k)); return d->kp[k - B].pos; }
|
||||
unsigned position (unsigned k) const
|
||||
{
|
||||
assert (operator % (k));
|
||||
return d->kp[k - B].pos;
|
||||
}
|
||||
|
||||
void write_self (writer &w) const;
|
||||
};
|
||||
|
||||
template<unsigned B> void
|
||||
ullmanset<B>::unref ()
|
||||
ullmanset<B>::data::delete_at_pos (unsigned p)
|
||||
{
|
||||
if (d && --d->refcount == 0)
|
||||
{
|
||||
delete [] (char *)d;
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned B> void
|
||||
ullmanset<B>::delete_at_pos (unsigned p)
|
||||
{
|
||||
assert (d);
|
||||
assert (p < d->n);
|
||||
unsigned n = --d->n;
|
||||
assert (p < n);
|
||||
--n;
|
||||
if (p != n)
|
||||
{
|
||||
unsigned ell = d->kp[n].key;
|
||||
d->kp[ell - B].pos = p;
|
||||
d->kp[p].key = ell;
|
||||
unsigned ell = kp[n].key;
|
||||
kp[ell - B].pos = p;
|
||||
kp[p].key = ell;
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned B>
|
||||
ullmanset<B>::ullmanset (unsigned size)
|
||||
: d(0)
|
||||
{
|
||||
data *newd = (data *)new char[sizeof (data)
|
||||
+ sizeof (keypos) * size
|
||||
- sizeof (keypos)];
|
||||
newd->refcount = 0;
|
||||
new (newd) data;
|
||||
newd->size = size;
|
||||
newd->n = 0;
|
||||
ref (newd);
|
||||
d = newd;
|
||||
}
|
||||
|
||||
template<unsigned B>
|
||||
ullmanset<B>::ullmanset (unsigned size, initializer_list<unsigned> il)
|
||||
: ullmanset(size)
|
||||
{
|
||||
for (unsigned i : il)
|
||||
operator += (i);
|
||||
}
|
||||
|
||||
template<unsigned B>
|
||||
ullmanset<B>::ullmanset (copy, const ullmanset &s)
|
||||
: d(0)
|
||||
: ullmanset(s.size ())
|
||||
{
|
||||
if (s.d)
|
||||
{
|
||||
unsigned bytes = (sizeof (data)
|
||||
+ sizeof (keypos) * s.d->size
|
||||
- sizeof (keypos));
|
||||
data *newd = (data *)new char[bytes];
|
||||
memcpy (newd, s.d, bytes);
|
||||
newd->refcount = 0;
|
||||
ref (newd);
|
||||
}
|
||||
d->n = s.d->n;
|
||||
memcpy (&d->kp[0], &s.d->kp[0], sizeof (keypos) * d->n);
|
||||
}
|
||||
|
||||
template<unsigned B>
|
||||
ullmanset<B>::ullmanset (reader &r)
|
||||
: d(0)
|
||||
: ullmanset(r.read_unsigned ())
|
||||
{
|
||||
unsigned size_ = r.read_unsigned ();
|
||||
if (size_ > 0)
|
||||
{
|
||||
data *newd = (data *)new char[sizeof (data) + sizeof (keypos) * (size_ - 1)];
|
||||
newd->refcount = 0;
|
||||
newd->size = size_;
|
||||
newd->n = 0;
|
||||
ref (newd);
|
||||
}
|
||||
|
||||
unsigned card_ = r.read_unsigned ();
|
||||
for (unsigned i = 0; i < card_; i ++)
|
||||
push (r.read_unsigned ());
|
||||
@ -179,8 +167,6 @@ ullmanset<B>::ullmanset (reader &r)
|
||||
template<unsigned B> bool
|
||||
ullmanset<B>::operator == (const ullmanset &s)
|
||||
{
|
||||
assert (d);
|
||||
assert (s.d);
|
||||
if (d->n != s.d->n)
|
||||
return 0;
|
||||
for (iter i = *this; i; i ++)
|
||||
@ -194,7 +180,6 @@ ullmanset<B>::operator == (const ullmanset &s)
|
||||
template<unsigned B> void
|
||||
ullmanset<B>::push (unsigned k)
|
||||
{
|
||||
assert (d);
|
||||
assert (!operator % (k));
|
||||
unsigned p = d->n ++;
|
||||
d->kp[p].key = k;
|
||||
@ -204,7 +189,6 @@ ullmanset<B>::push (unsigned k)
|
||||
template<unsigned B> void
|
||||
ullmanset<B>::operator += (unsigned k)
|
||||
{
|
||||
assert (d);
|
||||
assert ((k - B) >= 0);
|
||||
assert ((k - B) < d->size);
|
||||
if (!operator % (k))
|
||||
@ -218,13 +202,12 @@ ullmanset<B>::operator += (unsigned k)
|
||||
template<unsigned B> void
|
||||
ullmanset<B>::operator -= (unsigned k)
|
||||
{
|
||||
assert (d);
|
||||
assert ((k - B) >= 0);
|
||||
assert ((k - B) < d->size);
|
||||
if (operator % (k))
|
||||
{
|
||||
unsigned p = d->kp[k - B].pos;
|
||||
delete_at_pos (p);
|
||||
d->delete_at_pos (p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,22 +253,49 @@ ullmanset<B>::write_self (writer &w) const
|
||||
write (w, i.val ());
|
||||
}
|
||||
|
||||
template<unsigned B>
|
||||
class ullmanset_const_stl_iter
|
||||
{
|
||||
private:
|
||||
ptr<typename ullmanset<B>::data> d;
|
||||
unsigned p;
|
||||
|
||||
public:
|
||||
ullmanset_const_stl_iter (const ullmanset<B> &s, unsigned p_) : d(s.d), p(p_) { }
|
||||
|
||||
bool operator != (const ullmanset_const_stl_iter &end) const { return p != end.p; }
|
||||
unsigned operator * () const { assert (p < d->n); return d->kp[p].key; }
|
||||
ullmanset_const_stl_iter &operator ++ () { p ++; return *this; }
|
||||
};
|
||||
|
||||
template<unsigned B> ullmanset_const_stl_iter<B>
|
||||
ullmanset<B>::begin () const
|
||||
{
|
||||
return ullmanset_const_stl_iter<B> (*this, 0);
|
||||
}
|
||||
|
||||
template<unsigned B> ullmanset_const_stl_iter<B>
|
||||
ullmanset<B>::end () const
|
||||
{
|
||||
return ullmanset_const_stl_iter<B> (*this, d->n);
|
||||
}
|
||||
|
||||
template<unsigned B>
|
||||
class ullmanset_iter
|
||||
{
|
||||
private:
|
||||
ullmanset<B> &s;
|
||||
ptr<typename ullmanset<B>::data> d;
|
||||
unsigned i;
|
||||
bool deleted;
|
||||
|
||||
public:
|
||||
ullmanset_iter (ullmanset<B> &s_) : s(s_), i(0), deleted(0) { assert (s_.d); }
|
||||
ullmanset_iter (ullmanset<B> &s) : d(s.d), i(0), deleted(0) { }
|
||||
~ullmanset_iter () { }
|
||||
|
||||
void del () { assert (!deleted); assert (i < s.d->n); s.delete_at_pos (i); }
|
||||
unsigned val () const { assert (!deleted); assert (i < s.d->n); return s.d->kp[i].key; }
|
||||
unsigned pos () const { assert (!deleted); assert (i < s.d->n); return i; }
|
||||
operator bool () const { assert (!deleted); return i < s.d->n; }
|
||||
void del () { assert (!deleted); assert (i < d->n); d->delete_at_pos (i); }
|
||||
unsigned val () const { assert (!deleted); assert (i < d->n); return d->kp[i].key; }
|
||||
unsigned pos () const { assert (!deleted); assert (i < d->n); return i; }
|
||||
operator bool () const { assert (!deleted); return i < d->n; }
|
||||
void operator ++ () { if (deleted) deleted = 0; else i ++; }
|
||||
void operator ++ (int) { operator ++ (); }
|
||||
};
|
||||
@ -294,16 +304,16 @@ template<unsigned B>
|
||||
class ullmanset_const_iter
|
||||
{
|
||||
private:
|
||||
const ullmanset<B> &s;
|
||||
ptr<typename ullmanset<B>::data> d;
|
||||
unsigned i;
|
||||
|
||||
public:
|
||||
ullmanset_const_iter (const ullmanset<B> &s_) : s(s_), i(0) { assert (s_.d); }
|
||||
ullmanset_const_iter (const ullmanset<B> &s) : d(s.d), i(0) { }
|
||||
~ullmanset_const_iter () { }
|
||||
|
||||
unsigned val () const { assert (i < s.d->n); return s.d->kp[i].key; }
|
||||
unsigned pos () const { assert (i < s.d->n); return i; }
|
||||
operator bool () const { return i < s.d->n; }
|
||||
unsigned val () const { assert (i < d->n); return d->kp[i].key; }
|
||||
unsigned pos () const { assert (i < d->n); return i; }
|
||||
operator bool () const { return i < d->n; }
|
||||
void operator ++ () { i ++; }
|
||||
void operator ++ (int) { i ++; }
|
||||
};
|
||||
|
@ -36,8 +36,10 @@ public:
|
||||
|
||||
vector &operator = (const vector &v) { unref (); ref (v.d); return *this; }
|
||||
|
||||
bool operator < (const vector &v) const;
|
||||
bool operator == (const vector &v) const;
|
||||
bool operator != (const vector &v) const { return !operator == (v); }
|
||||
|
||||
bool operator < (const vector &v) const;
|
||||
|
||||
bool operator % (unsigned i) { return d && i < d->n; }
|
||||
|
||||
|
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
|
22
mpi_aux.h
Normal file
22
mpi_aux.h
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
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);
|
||||
|
||||
int recv_int (int *src);
|
||||
std::string recv_string (int *src);
|
||||
|
||||
inline int recv_int () { return recv_int (0); }
|
||||
inline std::string recv_string () { return recv_string (0); }
|
||||
|
||||
#if 0
|
||||
void send_htw_knot (unsigned n, bool alternating, unsigned k, int dest);
|
||||
knot_diagram recv_knot (int *src);
|
||||
knot_diagram recv_knot () { return recv_knot (0); }
|
||||
#endif
|
578
mpimain.cpp
Normal file
578
mpimain.cpp
Normal file
@ -0,0 +1,578 @@
|
||||
|
||||
#include <knotkit.h>
|
||||
|
||||
#include <mpi.h>
|
||||
#include <mpi_aux.h>
|
||||
|
||||
#define CMD_DO 1
|
||||
#define CMD_DIE 2
|
||||
|
||||
static const int block_size = 100;
|
||||
|
||||
void
|
||||
master ()
|
||||
{
|
||||
basedvector<knot_desc, 1> work;
|
||||
|
||||
for (unsigned i = 1; i <= 10; i ++)
|
||||
for (unsigned j = 1; j <= mt_links (i); j ++)
|
||||
{
|
||||
knot_diagram kd (mt_links (i, j));
|
||||
unsigned n = kd.num_components ();
|
||||
if (n < 2)
|
||||
continue;
|
||||
|
||||
work.append (knot_desc (knot_desc::MT, i, j));
|
||||
}
|
||||
|
||||
#if 0
|
||||
basedvector<basedvector<unsigned, 1>, 1> groups = mutant_knot_groups (15);
|
||||
|
||||
for (unsigned i = 1; i <= groups.size (); i ++)
|
||||
for (unsigned j = 1; j <= groups[i].size (); j ++)
|
||||
work.append (knot_desc (knot_desc::HTW, 15, groups[i][j]));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (unsigned i = 14; i >= 1; i --)
|
||||
{
|
||||
if (i <= 10)
|
||||
{
|
||||
for (unsigned j = 1; j <= rolfsen_crossing_knots (i); j += block_size)
|
||||
{
|
||||
work.append (knot_desc (ROLFSEN, i, j));
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned j = 1; j <= htw_knots (i); j += block_size)
|
||||
{
|
||||
work.append (knot_desc (HTW, i, j));
|
||||
}
|
||||
|
||||
if (i <= 13)
|
||||
{
|
||||
for (unsigned j = 1; j <= mt_links (i); j += block_size)
|
||||
{
|
||||
work.append (knot_desc (MT, i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ntasks = num_tasks ();
|
||||
|
||||
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, rank);
|
||||
send_int ((int)desc.i, rank);
|
||||
send_int ((int)desc.j, rank);
|
||||
|
||||
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, rank);
|
||||
send_int ((int)desc.i, rank);
|
||||
send_int ((int)desc.j, rank);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
file_exists (const char *file)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
if (stat (file, &stat_buf) != 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
stderror ("stat: %s", file);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
compute_forgetful (int rank, knot_desc desc, const char *buf)
|
||||
{
|
||||
knot_diagram kd = desc.diagram ();
|
||||
|
||||
typedef Zp<97> R;
|
||||
|
||||
unsigned n = kd.num_components ();
|
||||
assert (n >= 2);
|
||||
assert (n < 97);
|
||||
|
||||
printf ("[% 2d] ", rank);
|
||||
show (kd);
|
||||
newline ();
|
||||
|
||||
unionfind<1> u (kd.num_edges ());
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
{
|
||||
u.join (kd.ept_edge (kd.crossings[i][1]),
|
||||
kd.ept_edge (kd.crossings[i][3]));
|
||||
u.join (kd.ept_edge (kd.crossings[i][2]),
|
||||
kd.ept_edge (kd.crossings[i][4]));
|
||||
}
|
||||
|
||||
map<unsigned, unsigned> root_comp;
|
||||
unsigned t = 0;
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
{
|
||||
if (u.find (i) == i)
|
||||
{
|
||||
++ t;
|
||||
root_comp.push (i, t);
|
||||
}
|
||||
}
|
||||
assert (t == n);
|
||||
|
||||
basedvector<R, 1> comp_weight (n);
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
comp_weight[i] = R ((int)i);
|
||||
|
||||
map<unsigned, R> crossing_over_sign;
|
||||
|
||||
// crossings
|
||||
set<unsigned> pending;
|
||||
set<unsigned> finished;
|
||||
|
||||
crossing_over_sign.push (1, R (1));
|
||||
pending.push (1);
|
||||
|
||||
while (pending.card () > 0)
|
||||
{
|
||||
unsigned x = pending.pop ();
|
||||
finished.push (x);
|
||||
|
||||
R s = crossing_over_sign(x);
|
||||
|
||||
for (unsigned j = 1; j <= 4; j ++)
|
||||
{
|
||||
unsigned p = kd.crossings[x][j];
|
||||
R t = kd.is_over_ept (p) ? s : -s; // sign of (x, p)
|
||||
|
||||
unsigned q = kd.edge_other_ept (p);
|
||||
unsigned x2 = kd.ept_crossing[q];
|
||||
|
||||
R u = kd.is_over_ept (q) ? -t : t;
|
||||
|
||||
if (crossing_over_sign % x2)
|
||||
assert (crossing_over_sign(x2) == u);
|
||||
else
|
||||
crossing_over_sign.push (x2, u);
|
||||
|
||||
if (! (finished % x2))
|
||||
pending += x2;
|
||||
}
|
||||
}
|
||||
assert (finished.card () == kd.n_crossings);
|
||||
|
||||
#if 0
|
||||
printf ("crossing_over_sign:\n");
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
{
|
||||
printf (" % 2d: ", i);
|
||||
display (crossing_over_sign(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
cube<R> c (kd);
|
||||
#if 0
|
||||
for (unsigned i = 0; i < c.n_resolutions; i ++)
|
||||
{
|
||||
smallbitset state (kd.n_crossings, i);
|
||||
smoothing s (kd, state);
|
||||
s.show_self (kd, state);
|
||||
newline ();
|
||||
}
|
||||
#endif
|
||||
|
||||
mod_map<R> untwisted_d = c.compute_d (1, 0, 0, 0, 0);
|
||||
assert (untwisted_d.compose (untwisted_d) == 0);
|
||||
|
||||
mod_map<R> d = untwisted_d;
|
||||
for (unsigned x = 1; x <= kd.n_crossings; x ++)
|
||||
{
|
||||
unsigned p1 = kd.crossings[x][1],
|
||||
p2 = kd.crossings[x][2];
|
||||
assert (kd.is_over_ept (p2));
|
||||
|
||||
unsigned r1 = u.find (kd.ept_edge (p1)),
|
||||
r2 = u.find (kd.ept_edge (p2));
|
||||
|
||||
unsigned c1 = root_comp(r1),
|
||||
c2 = root_comp(r2);
|
||||
|
||||
if (c1 != c2)
|
||||
{
|
||||
R s = crossing_over_sign(x);
|
||||
|
||||
R w_under = comp_weight[c1];
|
||||
R w_over = comp_weight[c2];
|
||||
|
||||
d = d + c.compute_dinv (x)*(s*(w_over - w_under))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
// display ("d:\n", d);
|
||||
|
||||
// mod_map<Z> h = d.compose (d);
|
||||
// display ("h:\n", h);
|
||||
|
||||
assert (d.compose (d) == 0);
|
||||
|
||||
ptr<const module<R> > Ek = c.khC;
|
||||
mod_map<R> dk = d;
|
||||
|
||||
basedvector<multivariate_laurentpoly<Z>, 1> pages;
|
||||
|
||||
unsigned kinf;
|
||||
for (int dq = 0;; dq -= 2)
|
||||
{
|
||||
chain_complex_simplifier<R> s (Ek, dk, dq);
|
||||
Ek = s.new_C;
|
||||
dk = s.new_d;
|
||||
|
||||
pages.append (Ek->free_poincare_polynomial ());
|
||||
|
||||
printf ("[% 2d] ", rank);
|
||||
printf ("|E%d| = %d\n", ((- dq) / 2) + 1, Ek->dim ());
|
||||
if (dk == 0)
|
||||
{
|
||||
kinf = ((- dq) / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned total_lk = kd.total_linking_number ();
|
||||
|
||||
unsigned trivial_bound = total_lk == 0 ? 2 : total_lk;
|
||||
|
||||
printf ("[% 2d] ", rank);
|
||||
printf ("kinf = %d, trivial bound = %d (total_lk = %d)\n",
|
||||
kinf, trivial_bound, total_lk);
|
||||
|
||||
if (trivial_bound < kinf)
|
||||
{
|
||||
printf ("[% 2d] ", rank);
|
||||
printf (" > BETTER\n");
|
||||
}
|
||||
fflush (stdout);
|
||||
|
||||
assert (desc.t == knot_desc::MT);
|
||||
gzfile_writer w (buf);
|
||||
write (w, desc);
|
||||
write (w, pages);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned
|
||||
compute_b_lk_weak (knot_diagram &kd)
|
||||
{
|
||||
unsigned m = kd.num_components ();
|
||||
assert (m > 1);
|
||||
|
||||
if (m == 2)
|
||||
{
|
||||
unsigned total_lk = kd.total_linking_number ();
|
||||
return total_lk == 0 ? 2 : total_lk;
|
||||
}
|
||||
|
||||
unionfind<1> u (kd.num_edges ());
|
||||
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
{
|
||||
u.join (kd.ept_edge (kd.crossings[i][1]),
|
||||
kd.ept_edge (kd.crossings[i][3]));
|
||||
u.join (kd.ept_edge (kd.crossings[i][2]),
|
||||
kd.ept_edge (kd.crossings[i][4]));
|
||||
}
|
||||
assert (m == u.num_sets ());
|
||||
|
||||
map<unsigned, unsigned> root_comp;
|
||||
unsigned t = 0;
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
{
|
||||
if (u.find (i) == i)
|
||||
{
|
||||
++ t;
|
||||
root_comp.push (i, t);
|
||||
}
|
||||
}
|
||||
assert (t == m);
|
||||
|
||||
unsigned b_lk_weak = 0;
|
||||
|
||||
for (unsigned i = 1; i <= m; i ++)
|
||||
for (unsigned j = i + 1; j <= m; j ++)
|
||||
{
|
||||
assert (i < j);
|
||||
|
||||
int lk = 0;
|
||||
for (unsigned x = 1; x <= kd.n_crossings; x ++)
|
||||
{
|
||||
unsigned r1 = root_comp(u.find (kd.ept_edge (kd.crossings[x][1]))),
|
||||
r2 = root_comp(u.find (kd.ept_edge (kd.crossings[x][2])));
|
||||
if (((r1 == i) && (r2 == j))
|
||||
|| ((r2 == i) && (r1 == j)))
|
||||
{
|
||||
if (kd.is_to_ept (kd.crossings[x][1]) == kd.is_to_ept (kd.crossings[x][4]))
|
||||
lk ++;
|
||||
else
|
||||
lk --;
|
||||
}
|
||||
}
|
||||
assert (is_even (lk));
|
||||
lk /= 2;
|
||||
|
||||
if (lk == 0)
|
||||
{
|
||||
smallbitset ci (m);
|
||||
ci.push (i);
|
||||
|
||||
smallbitset cj (m);
|
||||
cj.push (j);
|
||||
|
||||
smallbitset c (m);
|
||||
c.push (i);
|
||||
c.push (j);
|
||||
knot_diagram Lij (SUBLINK, c, kd);
|
||||
|
||||
multivariate_laurentpoly<Z> P_Lij = Kh_poincare_polynomial<Z2> (Lij);
|
||||
|
||||
knot_diagram Li_join_Lj (DISJOINT_UNION,
|
||||
knot_diagram (SUBLINK, ci, kd),
|
||||
knot_diagram (SUBLINK, cj, kd));
|
||||
|
||||
multivariate_laurentpoly<Z> P_Li_join_Lj = Kh_poincare_polynomial<Z2> (Li_join_Lj);
|
||||
|
||||
if (P_Lij != P_Li_join_Lj)
|
||||
lk = 2; // non-split
|
||||
}
|
||||
|
||||
b_lk_weak += abs (lk);
|
||||
}
|
||||
|
||||
return b_lk_weak == 0 ? 2 : b_lk_weak;
|
||||
}
|
||||
|
||||
void
|
||||
compute_splitting_bounds (const knot_desc &desc)
|
||||
{
|
||||
typedef fraction_field<polynomial<Z2> > Z2x;
|
||||
|
||||
int rank = self_rank ();
|
||||
|
||||
knot_diagram kd = desc.diagram ();
|
||||
unsigned m = kd.num_components ();
|
||||
assert (m > 1);
|
||||
|
||||
printf ("[% 2d] ", rank); show (kd); newline ();
|
||||
printf ("[% 2d] m = %d\n", rank, m);
|
||||
|
||||
unsigned total_lk = kd.total_linking_number ();
|
||||
printf ("[% 2d] total_lk = %d\n", rank, total_lk);
|
||||
|
||||
unionfind<1> u (kd.num_edges ());
|
||||
|
||||
for (unsigned i = 1; i <= kd.n_crossings; i ++)
|
||||
{
|
||||
u.join (kd.ept_edge (kd.crossings[i][1]),
|
||||
kd.ept_edge (kd.crossings[i][3]));
|
||||
u.join (kd.ept_edge (kd.crossings[i][2]),
|
||||
kd.ept_edge (kd.crossings[i][4]));
|
||||
}
|
||||
assert (u.num_sets () == m);
|
||||
|
||||
map<unsigned, unsigned> root_comp;
|
||||
unsigned t = 0;
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
{
|
||||
if (u.find (i) == i)
|
||||
{
|
||||
++ t;
|
||||
root_comp.push (i, t);
|
||||
}
|
||||
}
|
||||
assert (t == m);
|
||||
|
||||
basedvector<Q, 1> comp_weightQ (m);
|
||||
for (unsigned i = 1; i <= m; i ++)
|
||||
comp_weightQ[i] = Q (i);
|
||||
unsigned bQ = splitting_bound<Q> (kd, comp_weightQ);
|
||||
|
||||
basedvector<Z2x, 1> comp_weightZ2x (m);
|
||||
for (unsigned i = 1; i <= m; i ++)
|
||||
comp_weightZ2x[i] = Z2x (polynomial<Z2> (Z2 (1), i));
|
||||
unsigned bZ2x = splitting_bound<Z2x> (kd, comp_weightZ2x);
|
||||
|
||||
// lower bound
|
||||
unsigned b = std::max (bQ, bZ2x);
|
||||
|
||||
// adjust parity
|
||||
if ((total_lk & 1) != (b & 1))
|
||||
b ++;
|
||||
|
||||
printf ("[% 2d] bQ = %d\n", rank, bQ);
|
||||
printf ("[% 2d] bZ2x = %d\n", rank, bZ2x);
|
||||
printf ("[% 2d] b = %d\n", rank, b);
|
||||
|
||||
unsigned b_lk_weaker = total_lk == 0 ? 2 : total_lk; // kd is non-split
|
||||
|
||||
unsigned b_lk_weak = compute_b_lk_weak (kd);
|
||||
assert (b_lk_weaker <= b_lk_weak);
|
||||
|
||||
printf ("[% 2d] b_lk_weaker = %d\n", rank, b_lk_weaker);
|
||||
printf ("[% 2d] b_lk_weak = %d\n", rank, b_lk_weak);
|
||||
|
||||
if (b_lk_weaker < b_lk_weak)
|
||||
printf ("[% 2d] > STRICTLY WEAKER\n", rank);
|
||||
|
||||
basedvector<basedvector<unsigned, 1>, 1> ps = permutations (m);
|
||||
unsigned upper = kd.n_crossings;
|
||||
for (unsigned i = 1; i <= ps.size (); i ++)
|
||||
{
|
||||
basedvector<unsigned, 1> p = ps[i];
|
||||
|
||||
unsigned ri = 0;
|
||||
for (unsigned j = 1; j <= kd.n_crossings; j ++)
|
||||
{
|
||||
unsigned upper_e = kd.ept_edge (kd.crossings[j][2]),
|
||||
lower_e = kd.ept_edge (kd.crossings[j][1]);
|
||||
|
||||
unsigned upper_c = root_comp(u.find (upper_e)),
|
||||
lower_c = root_comp(u.find (lower_e));
|
||||
|
||||
if (upper_c != lower_c
|
||||
&& p[upper_c] < p[lower_c])
|
||||
ri ++;
|
||||
}
|
||||
|
||||
if (ri < upper)
|
||||
upper = ri;
|
||||
}
|
||||
printf ("[% 2d] upper = %d\n", rank, upper);
|
||||
|
||||
assert (b_lk_weak <= upper);
|
||||
assert (b <= upper);
|
||||
|
||||
// non-trivial link, sp at least 1.
|
||||
unsigned best = std::max (b, b_lk_weak);
|
||||
|
||||
if (best == upper)
|
||||
printf ("[% 2d] > sp = %d", rank, upper);
|
||||
else
|
||||
printf ("[% 2d] > %d <= sp <= %d", rank, best, upper);
|
||||
|
||||
printf (" ");
|
||||
|
||||
if (b == best
|
||||
&& b_lk_weak == best)
|
||||
printf ("(b + b_lk_weak)");
|
||||
else if (b == best)
|
||||
printf ("(b)");
|
||||
else
|
||||
{
|
||||
assert (b_lk_weak == best);
|
||||
printf ("(b_lk_weak)");
|
||||
}
|
||||
fflush (stdout);
|
||||
|
||||
char buf[1000];
|
||||
assert (desc.t == knot_desc::MT);
|
||||
sprintf (buf, "splitting/L%d_%d.dat.gz\n", desc.i, desc.j);
|
||||
|
||||
{
|
||||
gzfile_reader r (buf);
|
||||
write (r, desc);
|
||||
write (r, bQ);
|
||||
write (r, bZ2x);
|
||||
write (r, b);
|
||||
write (r, b_lk_weak);
|
||||
write (r, upper);
|
||||
}
|
||||
}
|
||||
|
||||
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 = (unsigned)recv_int ();
|
||||
desc.j = (unsigned)recv_int ();
|
||||
|
||||
printf ("[% 2d] CMD_DO %s\n", rank, desc.name ().c_str ());
|
||||
|
||||
compute_splitting_bounds (desc);
|
||||
|
||||
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;
|
||||
}
|
20
parallel.cmd
Normal file
20
parallel.cmd
Normal file
@ -0,0 +1,20 @@
|
||||
# mpi job, runtime max 5days
|
||||
#PBS -l nodes=3:ppn=4,walltime=150:00:00
|
||||
# xxx PBS -l mem=80gb
|
||||
#
|
||||
# sends mail if the process aborts, when it begins, and
|
||||
# when it ends (abe)
|
||||
#PBS -m abe
|
||||
#
|
||||
module load openmpi/gcc
|
||||
# go to the directory with the program
|
||||
cd $HOME/src/knotkit
|
||||
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/u/cseed/llvm-3.1/lib
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
echo $LD_LIBRARY_PATH
|
||||
|
||||
# and run it
|
||||
numprocs=`wc -l <${PBS_NODEFILE}`
|
||||
mpiexec -np $numprocs ./mpimain
|
@ -19,21 +19,20 @@ planar_diagram::planar_diagram (const knot_diagram &kd)
|
||||
}
|
||||
|
||||
void
|
||||
planar_diagram::display_bohua () const
|
||||
planar_diagram::show_knottheory () const
|
||||
{
|
||||
printf ("%s\t[", name.c_str ());
|
||||
printf ("PD[");
|
||||
for (unsigned i = 1; i <= crossings.size (); i ++)
|
||||
{
|
||||
if (i > 1)
|
||||
printf (",");
|
||||
printf ("[%d,%d,%d,%d]",
|
||||
printf ("X[%d,%d,%d,%d]",
|
||||
crossings[i][1],
|
||||
crossings[i][2],
|
||||
crossings[i][3],
|
||||
crossings[i][4]);
|
||||
}
|
||||
printf ("]\n");
|
||||
|
||||
printf ("]");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -21,8 +21,9 @@ public:
|
||||
{ }
|
||||
~planar_diagram () { }
|
||||
|
||||
void display_bohua () const;
|
||||
|
||||
void show_knottheory () const;
|
||||
void display_knottheory () const { show_knottheory (); newline (); }
|
||||
|
||||
void show_self () const { printf ("planar_diagram %s", name.c_str ()); }
|
||||
void display_self () const;
|
||||
};
|
||||
|
@ -66,6 +66,7 @@ typedef int16_t flex_int16_t;
|
||||
typedef uint16_t flex_uint16_t;
|
||||
typedef int32_t flex_int32_t;
|
||||
typedef uint32_t flex_uint32_t;
|
||||
typedef uint64_t flex_uint64_t;
|
||||
#else
|
||||
typedef signed char flex_int8_t;
|
||||
typedef short int flex_int16_t;
|
||||
@ -172,7 +173,12 @@ typedef unsigned int flex_uint32_t;
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
#endif
|
||||
|
||||
extern int rd_yyleng;
|
||||
#ifndef YY_TYPEDEF_YY_SIZE_T
|
||||
#define YY_TYPEDEF_YY_SIZE_T
|
||||
typedef size_t yy_size_t;
|
||||
#endif
|
||||
|
||||
extern yy_size_t rd_yyleng;
|
||||
|
||||
extern FILE *rd_yyin, *rd_yyout;
|
||||
|
||||
@ -198,11 +204,6 @@ extern FILE *rd_yyin, *rd_yyout;
|
||||
|
||||
#define unput(c) yyunput( c, (yytext_ptr) )
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_SIZE_T
|
||||
#define YY_TYPEDEF_YY_SIZE_T
|
||||
typedef size_t yy_size_t;
|
||||
#endif
|
||||
|
||||
#ifndef YY_STRUCT_YY_BUFFER_STATE
|
||||
#define YY_STRUCT_YY_BUFFER_STATE
|
||||
struct yy_buffer_state
|
||||
@ -220,7 +221,7 @@ struct yy_buffer_state
|
||||
/* Number of characters read into yy_ch_buf, not including EOB
|
||||
* characters.
|
||||
*/
|
||||
int yy_n_chars;
|
||||
yy_size_t yy_n_chars;
|
||||
|
||||
/* Whether we "own" the buffer - i.e., we know we created it,
|
||||
* and can realloc() it to grow it, and should free() it to
|
||||
@ -290,8 +291,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
|
||||
|
||||
/* yy_hold_char holds the character lost when rd_yytext is formed. */
|
||||
static char yy_hold_char;
|
||||
static int yy_n_chars; /* number of characters read into yy_ch_buf */
|
||||
int rd_yyleng;
|
||||
static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
|
||||
yy_size_t rd_yyleng;
|
||||
|
||||
/* Points to current character in buffer. */
|
||||
static char *yy_c_buf_p = (char *) 0;
|
||||
@ -319,7 +320,7 @@ static void rd_yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
|
||||
|
||||
YY_BUFFER_STATE rd_yy_scan_buffer (char *base,yy_size_t size );
|
||||
YY_BUFFER_STATE rd_yy_scan_string (yyconst char *yy_str );
|
||||
YY_BUFFER_STATE rd_yy_scan_bytes (yyconst char *bytes,int len );
|
||||
YY_BUFFER_STATE rd_yy_scan_bytes (yyconst char *bytes,yy_size_t len );
|
||||
|
||||
void *rd_yyalloc (yy_size_t );
|
||||
void *rd_yyrealloc (void *,yy_size_t );
|
||||
@ -377,7 +378,7 @@ static void yy_fatal_error (yyconst char msg[] );
|
||||
*/
|
||||
#define YY_DO_BEFORE_ACTION \
|
||||
(yytext_ptr) = yy_bp; \
|
||||
rd_yyleng = (size_t) (yy_cp - yy_bp); \
|
||||
rd_yyleng = (yy_size_t) (yy_cp - yy_bp); \
|
||||
(yy_hold_char) = *yy_cp; \
|
||||
*yy_cp = '\0'; \
|
||||
(yy_c_buf_p) = yy_cp;
|
||||
@ -483,7 +484,7 @@ char *rd_yytext;
|
||||
|
||||
typedef yy::rd_parser::token token;
|
||||
typedef yy::rd_parser::token_type token_type;
|
||||
#line 487 "rd_parser/rd_scanner.cc"
|
||||
#line 488 "rd_parser/rd_scanner.cc"
|
||||
|
||||
#define INITIAL 0
|
||||
|
||||
@ -522,7 +523,7 @@ FILE *rd_yyget_out (void );
|
||||
|
||||
void rd_yyset_out (FILE * out_str );
|
||||
|
||||
int rd_yyget_leng (void );
|
||||
yy_size_t rd_yyget_leng (void );
|
||||
|
||||
char *rd_yyget_text (void );
|
||||
|
||||
@ -581,7 +582,7 @@ static int input (void );
|
||||
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
|
||||
{ \
|
||||
int c = '*'; \
|
||||
int n; \
|
||||
yy_size_t n; \
|
||||
for ( n = 0; n < max_size && \
|
||||
(c = getc( rd_yyin )) != EOF && c != '\n'; ++n ) \
|
||||
buf[n] = (char) c; \
|
||||
@ -666,7 +667,7 @@ YY_DECL
|
||||
#line 16 "rd_parser/rd_scanner.ll"
|
||||
|
||||
|
||||
#line 670 "rd_parser/rd_scanner.cc"
|
||||
#line 671 "rd_parser/rd_scanner.cc"
|
||||
|
||||
if ( !(yy_init) )
|
||||
{
|
||||
@ -794,7 +795,7 @@ YY_RULE_SETUP
|
||||
#line 49 "rd_parser/rd_scanner.ll"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 798 "rd_parser/rd_scanner.cc"
|
||||
#line 799 "rd_parser/rd_scanner.cc"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
yyterminate();
|
||||
|
||||
@ -981,7 +982,7 @@ static int yy_get_next_buffer (void)
|
||||
|
||||
else
|
||||
{
|
||||
int num_to_read =
|
||||
yy_size_t num_to_read =
|
||||
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
|
||||
|
||||
while ( num_to_read <= 0 )
|
||||
@ -995,7 +996,7 @@ static int yy_get_next_buffer (void)
|
||||
|
||||
if ( b->yy_is_our_buffer )
|
||||
{
|
||||
int new_size = b->yy_buf_size * 2;
|
||||
yy_size_t new_size = b->yy_buf_size * 2;
|
||||
|
||||
if ( new_size <= 0 )
|
||||
b->yy_buf_size += b->yy_buf_size / 8;
|
||||
@ -1026,7 +1027,7 @@ static int yy_get_next_buffer (void)
|
||||
|
||||
/* Read in more data. */
|
||||
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
|
||||
(yy_n_chars), (size_t) num_to_read );
|
||||
(yy_n_chars), num_to_read );
|
||||
|
||||
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
|
||||
}
|
||||
@ -1148,7 +1149,7 @@ static int yy_get_next_buffer (void)
|
||||
|
||||
else
|
||||
{ /* need more input */
|
||||
int offset = (yy_c_buf_p) - (yytext_ptr);
|
||||
yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
|
||||
++(yy_c_buf_p);
|
||||
|
||||
switch ( yy_get_next_buffer( ) )
|
||||
@ -1172,7 +1173,7 @@ static int yy_get_next_buffer (void)
|
||||
case EOB_ACT_END_OF_FILE:
|
||||
{
|
||||
if ( rd_yywrap( ) )
|
||||
return EOF;
|
||||
return 0;
|
||||
|
||||
if ( ! (yy_did_buffer_switch_on_eof) )
|
||||
YY_NEW_FILE;
|
||||
@ -1424,7 +1425,7 @@ void rd_yypop_buffer_state (void)
|
||||
*/
|
||||
static void rd_yyensure_buffer_stack (void)
|
||||
{
|
||||
int num_to_alloc;
|
||||
yy_size_t num_to_alloc;
|
||||
|
||||
if (!(yy_buffer_stack)) {
|
||||
|
||||
@ -1521,12 +1522,11 @@ YY_BUFFER_STATE rd_yy_scan_string (yyconst char * yystr )
|
||||
*
|
||||
* @return the newly allocated buffer state object.
|
||||
*/
|
||||
YY_BUFFER_STATE rd_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
|
||||
YY_BUFFER_STATE rd_yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
|
||||
{
|
||||
YY_BUFFER_STATE b;
|
||||
char *buf;
|
||||
yy_size_t n;
|
||||
int i;
|
||||
yy_size_t n, i;
|
||||
|
||||
/* Get memory for full buffer, including space for trailing EOB's. */
|
||||
n = _yybytes_len + 2;
|
||||
@ -1608,7 +1608,7 @@ FILE *rd_yyget_out (void)
|
||||
/** Get the length of the current token.
|
||||
*
|
||||
*/
|
||||
int rd_yyget_leng (void)
|
||||
yy_size_t rd_yyget_leng (void)
|
||||
{
|
||||
return rd_yyleng;
|
||||
}
|
||||
|
15
serial.cmd
Normal file
15
serial.cmd
Normal file
@ -0,0 +1,15 @@
|
||||
# serial job
|
||||
#PBS -l nodes=1:ppn=1,walltime=4:00:00
|
||||
# xxx PBS -l mem=80gb
|
||||
#
|
||||
# sends mail if the process aborts, when it begins, and
|
||||
# when it ends (abe)
|
||||
#PBS -m abe
|
||||
#
|
||||
# load intel compiler settings before running the program
|
||||
# since we compiled it with intel 10.1
|
||||
# module load intel/10.1
|
||||
# go to the directory with the program
|
||||
cd $HOME/src/knotkit
|
||||
# and run it
|
||||
LD_LIBRARY_PATH=/u/cseed/llvm-3.1/lib ./main
|
249
simplify_chain_complex.h
Normal file
249
simplify_chain_complex.h
Normal file
@ -0,0 +1,249 @@
|
||||
|
||||
template<class R> class simplified_complex_generators
|
||||
{
|
||||
unsigned new_n;
|
||||
ptr<const module<R> > C;
|
||||
basedvector<unsigned, 1> new_C_to_C_generator;
|
||||
|
||||
public:
|
||||
simplified_complex_generators (const simplified_complex_generators &g)
|
||||
: new_n(g.new_n),
|
||||
C(g.C),
|
||||
new_C_to_C_generator(g.new_C_to_C_generator)
|
||||
{ }
|
||||
simplified_complex_generators (unsigned new_n_,
|
||||
ptr<const module<R> > C_,
|
||||
basedvector<unsigned, 1> new_C_to_C_generator_)
|
||||
: new_n(new_n_),
|
||||
C(C_),
|
||||
new_C_to_C_generator(new_C_to_C_generator_)
|
||||
{ }
|
||||
~simplified_complex_generators () { }
|
||||
|
||||
simplified_complex_generators &operator = (const simplified_complex_generators &); // doesn't exist
|
||||
|
||||
unsigned dim () const { return new_n; }
|
||||
unsigned free_rank () const { return new_n; }
|
||||
grading generator_grading (unsigned i) const { return C->generator_grading (new_C_to_C_generator[i]); }
|
||||
void show_generator (unsigned i) const { C->show_generator (new_C_to_C_generator[i]); }
|
||||
R generator_ann (unsigned i) const { abort (); }
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class chain_complex_simplifier
|
||||
{
|
||||
public:
|
||||
ptr<const module<R> > C;
|
||||
unsigned n; // |C|
|
||||
mod_map<R> d;
|
||||
|
||||
ptr<const module<R> > new_C;
|
||||
mod_map<R> new_d;
|
||||
|
||||
// pi : C -> new_C
|
||||
mod_map<R> pi;
|
||||
|
||||
// iota : new_C -> C
|
||||
mod_map<R> iota;
|
||||
|
||||
private:
|
||||
set<unsigned> canceled;
|
||||
|
||||
basedvector<R, 1> cancel_binv;
|
||||
basedvector<unsigned, 1> cancel_j;
|
||||
basedvector<linear_combination<R>, 1> cancel_di;
|
||||
|
||||
basedvector<linear_combination<R>, 1> new_d_columns;
|
||||
basedvector<set<unsigned>, 1> preim;
|
||||
|
||||
basedvector<linear_combination<R>, 1> iota_columns;
|
||||
|
||||
void cancel (unsigned i, R b, unsigned j);
|
||||
|
||||
public:
|
||||
chain_complex_simplifier (ptr<const module<R> > C_,
|
||||
const mod_map<R> &d_,
|
||||
maybe<int> dh, maybe<int> dq);
|
||||
};
|
||||
|
||||
template<class R> void
|
||||
chain_complex_simplifier<R>::cancel (unsigned i, R b, unsigned j)
|
||||
{
|
||||
assert (i != j);
|
||||
assert (b.is_unit ());
|
||||
|
||||
R binv = b.recip ();
|
||||
|
||||
canceled.push (i);
|
||||
canceled.push (j);
|
||||
|
||||
new_d_columns[i].yank (j);
|
||||
preim[j].yank (i);
|
||||
|
||||
for (linear_combination_const_iter<R> k = new_d_columns[i]; k; k ++)
|
||||
preim[k.key ()].yank (i);
|
||||
for (set_const_iter<unsigned> k = preim[i]; k; k ++)
|
||||
new_d_columns[k.val ()].yank (i);
|
||||
for (linear_combination_const_iter<R> k = new_d_columns[j]; k; k ++)
|
||||
preim[k.key ()].yank (j);
|
||||
|
||||
for (set_const_iter<unsigned> kk = preim[j]; kk; kk ++)
|
||||
{
|
||||
unsigned k = kk.val ();
|
||||
R a = new_d_columns[k](j);
|
||||
assert (a != 0);
|
||||
|
||||
iota_columns[k].mulsub (a * binv, iota_columns[i]);
|
||||
}
|
||||
|
||||
iota_columns[i].clear ();
|
||||
iota_columns[j].clear ();
|
||||
|
||||
for (set_const_iter<unsigned> kk = preim[j]; kk; kk ++)
|
||||
{
|
||||
unsigned k = kk.val ();
|
||||
R a = new_d_columns[k](j);
|
||||
assert (a != 0);
|
||||
|
||||
R abinv = a * binv;
|
||||
|
||||
for (linear_combination_const_iter<R> ll = new_d_columns[i]; ll; ll ++)
|
||||
{
|
||||
unsigned ell = ll.key ();
|
||||
R c = ll.val ();
|
||||
|
||||
assert (! (canceled % k));
|
||||
assert (! (canceled % ell));
|
||||
assert (k != i);
|
||||
assert (k != j);
|
||||
assert (ell != i);
|
||||
assert (ell != j);
|
||||
assert (ell != k);
|
||||
|
||||
new_d_columns[k].mulsub (abinv * c, ell);
|
||||
if (new_d_columns[k] % ell)
|
||||
preim[ell] += k;
|
||||
else
|
||||
preim[ell] -= k;
|
||||
}
|
||||
}
|
||||
|
||||
for (set_const_iter<unsigned> k = preim[j]; k; k ++)
|
||||
new_d_columns[k.val ()].yank (j);
|
||||
|
||||
cancel_binv.append (binv);
|
||||
cancel_j.append (j);
|
||||
cancel_di.append (new_d_columns[i]);
|
||||
|
||||
new_d_columns[i] = linear_combination<R> ();
|
||||
preim[i].clear ();
|
||||
new_d_columns[j].clear ();
|
||||
preim[j].clear ();
|
||||
}
|
||||
|
||||
template<class R>
|
||||
chain_complex_simplifier<R>::chain_complex_simplifier (ptr<const module<R> > C_,
|
||||
const mod_map<R> &d_,
|
||||
maybe<int> dh, maybe<int> dq)
|
||||
: C(C_), n(C_->dim ()), d(d_),
|
||||
new_d_columns(n),
|
||||
preim(n),
|
||||
iota_columns(n)
|
||||
{
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
{
|
||||
new_d_columns[i] = d.column_copy (i);
|
||||
|
||||
for (linear_combination_const_iter<R> j = new_d_columns[i]; j; j ++)
|
||||
preim[j.key ()].push (i);
|
||||
|
||||
linear_combination<R> x (C);
|
||||
x.muladd (1, i);
|
||||
iota_columns[i] = x;
|
||||
}
|
||||
|
||||
for (unsigned i = n; i >= 1; i --)
|
||||
{
|
||||
if (canceled % i)
|
||||
continue;
|
||||
|
||||
grading igr = C->generator_grading (i);
|
||||
for (linear_combination_const_iter<R> j = new_d_columns[i]; j; j ++)
|
||||
{
|
||||
grading jgr = C->generator_grading (j.key ());
|
||||
if (j.val ().is_unit ()
|
||||
&& (dh.is_none ()
|
||||
|| (jgr.h - igr.h == dh.some ()))
|
||||
&& (dq.is_none ()
|
||||
|| (jgr.q - igr.q == dq.some ())))
|
||||
{
|
||||
cancel (i, j.val (), j.key ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ??? might not be completely simplified
|
||||
|
||||
unsigned new_n = n - canceled.card ();
|
||||
basedvector<unsigned, 1> new_C_to_C_generator (new_n),
|
||||
C_to_new_C_generator (n);
|
||||
for (unsigned i = 1, j = 1; i <= n; i ++)
|
||||
{
|
||||
if (canceled % i)
|
||||
{
|
||||
C_to_new_C_generator[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
C_to_new_C_generator[i] = j;
|
||||
new_C_to_C_generator[j] = i;
|
||||
j ++;
|
||||
}
|
||||
|
||||
new_C = (new base_module<R, simplified_complex_generators<R> >
|
||||
(simplified_complex_generators<R> (new_n, C, new_C_to_C_generator)));
|
||||
map_builder<R> db (new_C);
|
||||
|
||||
for (unsigned i = 1; i <= new_n; i ++)
|
||||
{
|
||||
unsigned i0 = new_C_to_C_generator[i];
|
||||
|
||||
for (linear_combination_const_iter<R> j0 = new_d_columns[i0]; j0; j0 ++)
|
||||
{
|
||||
unsigned j = C_to_new_C_generator[j0.key ()];
|
||||
assert (j != 0);
|
||||
|
||||
db[i].muladd (j0.val (), j);
|
||||
}
|
||||
}
|
||||
new_d = mod_map<R> (db);
|
||||
|
||||
map_builder<R> iotab (new_C, C);
|
||||
|
||||
for (unsigned i = 1; i <= new_n; i ++)
|
||||
iotab[i] = iota_columns[new_C_to_C_generator[i]];
|
||||
iota = mod_map<R> (iotab);
|
||||
|
||||
map_builder<R> pib (C, new_C);
|
||||
for (unsigned i = 1; i <= new_n; i ++)
|
||||
pib[new_C_to_C_generator[i]].muladd (1, i);
|
||||
|
||||
while (cancel_binv.size () > 0)
|
||||
{
|
||||
R binv = cancel_binv.pop ();
|
||||
unsigned j = cancel_j.pop ();
|
||||
linear_combination<R> di = cancel_di.pop ();
|
||||
|
||||
for (linear_combination_const_iter<R> ll = di; ll; ll ++)
|
||||
{
|
||||
R c = ll.val ();
|
||||
pib[j].mulsub (binv * c, pib[ll.key ()]);
|
||||
}
|
||||
}
|
||||
pi = mod_map<R> (pib);
|
||||
|
||||
assert (d.compose (iota) == iota.compose (new_d));
|
||||
assert (new_d.compose (pi) == pi.compose (d));
|
||||
assert (pi.compose (iota) == mod_map<R> (new_C, 1));
|
||||
}
|
@ -25,6 +25,9 @@ class spanning_tree_complex
|
||||
|
||||
mod_map<R> totally_twisted_kh_d () const;
|
||||
mod_map<R> twisted_d2 () const;
|
||||
mod_map<R> twisted_d2Un (unsigned n) const;
|
||||
|
||||
mod_map<R> twisted_d2U1_test () const;
|
||||
};
|
||||
|
||||
template<class F>
|
||||
@ -39,7 +42,7 @@ public:
|
||||
tree_generators (const spanning_tree_complex<F> &c_) : c(c_) { }
|
||||
~tree_generators () { }
|
||||
|
||||
tree_generators &operator = (const tree_generators &); // doesn't exist
|
||||
tree_generators &operator = (const tree_generators &) = delete;
|
||||
|
||||
unsigned dim () const { return c.trees.size (); }
|
||||
unsigned free_rank () const { return c.trees.size (); }
|
||||
@ -210,6 +213,291 @@ spanning_tree_complex<F>::twisted_d2 () const
|
||||
return mod_map<R> (b);
|
||||
}
|
||||
|
||||
template<class F> mod_map<fraction_field<polynomial<F> > >
|
||||
spanning_tree_complex<F>::twisted_d2Un (unsigned n) const
|
||||
{
|
||||
assert (kd.marked_edge);
|
||||
assert (n >= 1);
|
||||
|
||||
map_builder<R> b (C);
|
||||
|
||||
basedvector<int, 1> edge_weight (kd.num_edges ());
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
edge_weight[i] = 1; // (1 << i);
|
||||
|
||||
int total_weight = 0;
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
total_weight += edge_weight[i];
|
||||
|
||||
int shift = 2 * total_weight * n;
|
||||
|
||||
for (unsigned i = 1; i <= trees.size (); i ++)
|
||||
{
|
||||
set<unsigned> t = trees[i];
|
||||
|
||||
smallbitset r (kd.n_crossings);
|
||||
for (unsigned k = 1; k <= kd.n_crossings; k ++)
|
||||
{
|
||||
if ((edge_height[k] == 1) == (t % k))
|
||||
r.push (k);
|
||||
}
|
||||
smoothing s (kd, r);
|
||||
|
||||
for (set_const_iter<unsigned> ee = t; ee; ee ++)
|
||||
{
|
||||
unsigned e = ee.val ();
|
||||
|
||||
if (edge_height[e] != 0)
|
||||
continue;
|
||||
|
||||
for (unsigned f = 1; f <= bg.num_edges (); f ++)
|
||||
{
|
||||
if (edge_height[f] != 1 || (t % f))
|
||||
continue;
|
||||
|
||||
set<unsigned> t2 (COPY, t);
|
||||
t2.yank (e);
|
||||
t2.push (f);
|
||||
unsigned j = tree_idx(t2, 0);
|
||||
if (j == 0)
|
||||
continue;
|
||||
|
||||
bool neg = 0;
|
||||
for (unsigned a = kd.marked_edge;;)
|
||||
{
|
||||
unsigned p = s.edge_to (kd, a);
|
||||
if (kd.ept_crossing[p] == e)
|
||||
{
|
||||
if (s.is_crossing_from_ept (kd, r, p))
|
||||
neg = s.crossing_from_inside (kd, r, e);
|
||||
else
|
||||
neg = s.crossing_to_inside (kd, r, e);
|
||||
break;
|
||||
}
|
||||
else if (kd.ept_crossing[p] == f)
|
||||
{
|
||||
if (s.is_crossing_from_ept (kd, r, p))
|
||||
neg = s.crossing_from_inside (kd, r, f);
|
||||
else
|
||||
neg = s.crossing_to_inside (kd, r, f);
|
||||
break;
|
||||
}
|
||||
|
||||
a = s.next_edge (kd, r, a);
|
||||
assert (a != kd.marked_edge);
|
||||
}
|
||||
|
||||
set<unsigned> neither (COPY, t);
|
||||
neither.yank (e);
|
||||
|
||||
smallbitset neither_r (kd.n_crossings);
|
||||
for (unsigned k = 1; k <= kd.n_crossings; k ++)
|
||||
{
|
||||
if ((edge_height[k] == 1) == (neither % k))
|
||||
neither_r.push (k);
|
||||
}
|
||||
smoothing neither_s (kd, neither_r);
|
||||
|
||||
set<unsigned> both (COPY, t);
|
||||
both.push (f);
|
||||
|
||||
int A = 0;
|
||||
for (unsigned k = 1; k <= kd.num_edges (); k ++)
|
||||
{
|
||||
if (neither_s.edge_circle[k]
|
||||
!= neither_s.edge_circle[kd.marked_edge])
|
||||
A += edge_weight[k];
|
||||
}
|
||||
|
||||
smallbitset both_r (kd.n_crossings);
|
||||
for (unsigned k = 1; k <= kd.n_crossings; k ++)
|
||||
{
|
||||
if ((edge_height[k] == 1) == (both % k))
|
||||
both_r.push (k);
|
||||
}
|
||||
smoothing both_s (kd, both_r);
|
||||
|
||||
int B = 0;
|
||||
for (unsigned k = 1; k <= kd.num_edges (); k ++)
|
||||
{
|
||||
if (both_s.edge_circle[k]
|
||||
!= both_s.edge_circle[kd.marked_edge])
|
||||
B += edge_weight[k];
|
||||
}
|
||||
|
||||
assert (A >= 0 && B >= 0);
|
||||
|
||||
R x;
|
||||
|
||||
for (int k = 1; k <= (int)n; k ++)
|
||||
{
|
||||
if (n % k == 0)
|
||||
{
|
||||
int l = n / k;
|
||||
assert (k * l == (int)n);
|
||||
|
||||
assert (shift >= k*A + l*B);
|
||||
|
||||
if (neg) // ^ (bool)((n + 1) & 1))
|
||||
{
|
||||
x += R (polynomial<F> (1, (unsigned)(shift + k*A + l*B)));
|
||||
x += R (polynomial<F> (1, (unsigned)(shift - k*A - l*B)));
|
||||
}
|
||||
else
|
||||
{
|
||||
x += R (polynomial<F> (1, (unsigned)(shift - k*A + l*B)));
|
||||
x += R (polynomial<F> (1, (unsigned)(shift + k*A - l*B)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b[i].muladd (x, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mod_map<R> (b);
|
||||
}
|
||||
|
||||
template<class F> mod_map<fraction_field<polynomial<F> > >
|
||||
spanning_tree_complex<F>::twisted_d2U1_test () const
|
||||
{
|
||||
assert (kd.marked_edge);
|
||||
|
||||
map_builder<R> b (C);
|
||||
|
||||
basedvector<int, 1> edge_weight (kd.num_edges ());
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
edge_weight[i] = 1; // (1 << i);
|
||||
|
||||
int total_weight = 0;
|
||||
for (unsigned i = 1; i <= kd.num_edges (); i ++)
|
||||
total_weight += edge_weight[i];
|
||||
|
||||
int shift = 2 * total_weight;
|
||||
|
||||
for (unsigned i = 1; i <= trees.size (); i ++)
|
||||
{
|
||||
set<unsigned> t = trees[i];
|
||||
|
||||
smallbitset r (kd.n_crossings);
|
||||
for (unsigned k = 1; k <= kd.n_crossings; k ++)
|
||||
{
|
||||
if ((edge_height[k] == 1) == (t % k))
|
||||
r.push (k);
|
||||
}
|
||||
smoothing s (kd, r);
|
||||
|
||||
for (set_const_iter<unsigned> ee = t; ee; ee ++)
|
||||
{
|
||||
unsigned e = ee.val ();
|
||||
|
||||
if (edge_height[e] != 0)
|
||||
continue;
|
||||
|
||||
for (unsigned f = 1; f <= bg.num_edges (); f ++)
|
||||
{
|
||||
if (edge_height[f] != 1 || (t % f))
|
||||
continue;
|
||||
|
||||
set<unsigned> t2 (COPY, t);
|
||||
t2.yank (e);
|
||||
t2.push (f);
|
||||
unsigned j = tree_idx(t2, 0);
|
||||
if (j == 0)
|
||||
continue;
|
||||
|
||||
bool neg = 0;
|
||||
for (unsigned a = kd.marked_edge;;)
|
||||
{
|
||||
unsigned p = s.edge_to (kd, a);
|
||||
if (kd.ept_crossing[p] == e)
|
||||
{
|
||||
if (s.is_crossing_from_ept (kd, r, p))
|
||||
neg = s.crossing_from_inside (kd, r, e);
|
||||
else
|
||||
neg = s.crossing_to_inside (kd, r, e);
|
||||
break;
|
||||
}
|
||||
else if (kd.ept_crossing[p] == f)
|
||||
{
|
||||
if (s.is_crossing_from_ept (kd, r, p))
|
||||
neg = s.crossing_from_inside (kd, r, f);
|
||||
else
|
||||
neg = s.crossing_to_inside (kd, r, f);
|
||||
break;
|
||||
}
|
||||
|
||||
a = s.next_edge (kd, r, a);
|
||||
assert (a != kd.marked_edge);
|
||||
}
|
||||
|
||||
set<unsigned> neither (COPY, t);
|
||||
neither.yank (e);
|
||||
|
||||
smallbitset neither_r (kd.n_crossings);
|
||||
for (unsigned k = 1; k <= kd.n_crossings; k ++)
|
||||
{
|
||||
if ((edge_height[k] == 1) == (neither % k))
|
||||
neither_r.push (k);
|
||||
}
|
||||
smoothing neither_s (kd, neither_r);
|
||||
|
||||
set<unsigned> both (COPY, t);
|
||||
both.push (f);
|
||||
|
||||
int A = 0;
|
||||
for (unsigned k = 1; k <= kd.num_edges (); k ++)
|
||||
{
|
||||
if (neither_s.edge_circle[k]
|
||||
!= neither_s.edge_circle[kd.marked_edge])
|
||||
A += edge_weight[k];
|
||||
}
|
||||
|
||||
smallbitset both_r (kd.n_crossings);
|
||||
for (unsigned k = 1; k <= kd.n_crossings; k ++)
|
||||
{
|
||||
if ((edge_height[k] == 1) == (both % k))
|
||||
both_r.push (k);
|
||||
}
|
||||
smoothing both_s (kd, both_r);
|
||||
|
||||
int B = 0;
|
||||
for (unsigned k = 1; k <= kd.num_edges (); k ++)
|
||||
{
|
||||
if (both_s.edge_circle[k]
|
||||
!= both_s.edge_circle[kd.marked_edge])
|
||||
B += edge_weight[k];
|
||||
}
|
||||
|
||||
assert (A >= 0 && B >= 0);
|
||||
|
||||
printf ("A = %d, B = %d\n", A, B);
|
||||
|
||||
R x;
|
||||
|
||||
// worked:
|
||||
// bad: -, -/+, +
|
||||
assert (shift >= A && shift >= B);
|
||||
if (neg)
|
||||
{
|
||||
x += R (polynomial<F> (1, (unsigned)(shift + A)));
|
||||
x += R (polynomial<F> (1, (unsigned)(shift - B)));
|
||||
}
|
||||
else
|
||||
{
|
||||
x += R (polynomial<F> (1, (unsigned)(shift - A)));
|
||||
x += R (polynomial<F> (1, (unsigned)(shift + B)));
|
||||
}
|
||||
|
||||
b[i].muladd (x, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mod_map<R> (b);
|
||||
}
|
||||
|
||||
template<class F> mod_map<fraction_field<polynomial<F> > >
|
||||
spanning_tree_complex<F>::totally_twisted_kh_d () const
|
||||
{
|
||||
|
114
sseq.cpp
114
sseq.cpp
@ -2,7 +2,8 @@
|
||||
#include <knotkit.h>
|
||||
|
||||
sseq_page::sseq_page (const sseq_bounds &b)
|
||||
: rank(b.width ()),
|
||||
: k(0),
|
||||
rank(b.width ()),
|
||||
im_rank(b.width ())
|
||||
{
|
||||
for (unsigned i = 0; i < b.width (); i ++)
|
||||
@ -140,87 +141,6 @@ sseq_page::delta_poincare_polynomial (const sseq_bounds &b) const
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
sseq_page::texshow (FILE *fp, const sseq_bounds &b, unsigned dh, bool last)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\begin{tikzpicture}[scale=.66]\n\
|
||||
\\draw[->] (0,0) -- (%d.5,0) node[right] {$t$};\n\
|
||||
\\draw[->] (0,0) -- (0,%d.5) node[above] {$q$};\n\
|
||||
\\draw[step=1] (0,0) grid (%d,%d);\n",
|
||||
b.width (), (b.height () + 1) / 2, b.width (), (b.height () + 1) / 2);
|
||||
|
||||
fprintf (fp, " \\draw (%.3f,-0.8) node[below] {$",
|
||||
((double)b.width () + 0.5) / 2);
|
||||
if (last)
|
||||
fprintf (fp, "E_\\infty = ");
|
||||
fprintf (fp, "E_{%d}$};\n",
|
||||
dh);
|
||||
|
||||
/* label axes */
|
||||
for (int x = b.minh; x <= b.maxh; x ++)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\draw (%d.5,-.2) node[below] {$%d$};\n",
|
||||
x - b.minh, x);
|
||||
}
|
||||
for (int y = b.minq; y <= b.maxq; y += 2)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\draw (-.2,%d.5) node[left] {$%d$};\n",
|
||||
(y - b.minq) / 2, y);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < b.width (); i ++)
|
||||
for (unsigned j = 0; j < b.height (); j ++)
|
||||
{
|
||||
int r = rank[i][j];
|
||||
if (r == 1)
|
||||
{
|
||||
assert (is_even (j));
|
||||
fprintf (fp, "\
|
||||
\\fill (%d.5, %d.5) circle (.15);\n",
|
||||
i, j / 2);
|
||||
}
|
||||
else if (r > 1)
|
||||
{
|
||||
assert (is_even (j));
|
||||
fprintf (fp, "\
|
||||
\\draw (%d.5, %d.5) node {$%d$};\n",
|
||||
i, j / 2, r);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < b.width (); i ++)
|
||||
for (unsigned j = 0; j < b.height (); j ++)
|
||||
{
|
||||
unsigned r = im_rank[i][j];
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
unsigned dx = dh,
|
||||
dy = dh - 1; // in "boxes"
|
||||
assert (dx >= 2); // eliminated d_1
|
||||
|
||||
double h = sqrt ((double)(dx * dx + dy * dy));
|
||||
double xadj = (double)dx / h * 0.3;
|
||||
double yadj = (double)dy / h * 0.3;
|
||||
|
||||
assert (is_even (j));
|
||||
fprintf (fp, " \\draw[->] (%.3f, %.3f) -- ",
|
||||
(double)i + 0.5 + xadj, (double)(j / 2) + 0.5 + yadj);
|
||||
if (r > 1)
|
||||
fprintf (fp, "node[color=red!75!black] {$%d$} ", r);
|
||||
fprintf (fp, "(%.3f, %.3f);\n",
|
||||
(double)(i + dx) + 0.5 - xadj, (double)(j / 2 + dy) + 0.5 - yadj);
|
||||
}
|
||||
|
||||
fprintf (fp, "\
|
||||
\\end{tikzpicture}\n");
|
||||
|
||||
fflush (fp);
|
||||
}
|
||||
|
||||
sseq
|
||||
sseq::operator + (const sseq &ss2) const
|
||||
{
|
||||
@ -280,36 +200,6 @@ sseq::shift (int dh, int dq) const
|
||||
pages);
|
||||
}
|
||||
|
||||
bool
|
||||
sseq::equal_as_spaces (const sseq &ss) const
|
||||
{
|
||||
if (bounds != ss.bounds
|
||||
|| pages.size () != ss.pages.size ())
|
||||
return 0;
|
||||
|
||||
for (unsigned i = 1; i <= pages.size (); i ++)
|
||||
{
|
||||
if (!pages[i].equal_as_spaces (ss.pages[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
sseq::texshow (FILE *fp, std::string name)
|
||||
{
|
||||
fprintf (fp, "\\section{Knot $%s$}\n", name.c_str ());
|
||||
|
||||
unsigned n = pages.size ();
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
fprintf (fp, "$\\rank E_%d = %d$ \\\\\n",
|
||||
i + 1, pages[i].total_rank ());
|
||||
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
pages[i].texshow (fp, bounds, i + 1, i == n);
|
||||
}
|
||||
|
||||
void
|
||||
sseq_builder::cancel (unsigned d)
|
||||
{
|
||||
|
435
sseq.h
435
sseq.h
@ -7,6 +7,27 @@ class sseq_bounds
|
||||
|
||||
public:
|
||||
sseq_bounds () { }
|
||||
|
||||
template<class R, class M> sseq_bounds (ptr<const module<R> > C, M m)
|
||||
{
|
||||
grading hq1 = m(C->generator_grading (1));
|
||||
minh = maxh = hq1.h;
|
||||
minq = maxq = hq1.q;
|
||||
|
||||
for (unsigned i = 2; i <= C->dim (); i ++)
|
||||
{
|
||||
grading hq = m(C->generator_grading (i));
|
||||
if (hq.h < minh)
|
||||
minh = hq.h;
|
||||
if (hq.h > maxh)
|
||||
maxh = hq.h;
|
||||
if (hq.q < minq)
|
||||
minq = hq.q;
|
||||
if (hq.q > maxq)
|
||||
maxq = hq.q;
|
||||
}
|
||||
}
|
||||
|
||||
sseq_bounds (int minh_, int maxh_, int minq_, int maxq_)
|
||||
: minh(minh_), maxh(maxh_), minq(minq_), maxq(maxq_)
|
||||
{ }
|
||||
@ -34,25 +55,40 @@ class sseq_bounds
|
||||
&& minq == b.minq
|
||||
&& maxq == b.maxq;
|
||||
}
|
||||
bool operator != (const sseq_bounds &b) const { return !operator == (b); }
|
||||
};
|
||||
|
||||
class sseq_page
|
||||
{
|
||||
public:
|
||||
/* bounds come from sseq */
|
||||
unsigned k;
|
||||
grading dk_gr;
|
||||
vector<vector<unsigned> > rank,
|
||||
im_rank;
|
||||
|
||||
public:
|
||||
sseq_page () { }
|
||||
sseq_page (const sseq_bounds &b);
|
||||
template<class R, class M> sseq_page (const sseq_bounds &b,
|
||||
unsigned k_,
|
||||
grading dk_gr_,
|
||||
mod_map<R> d,
|
||||
M m);
|
||||
sseq_page (const sseq_page &pg)
|
||||
: rank(pg.rank), im_rank(pg.im_rank)
|
||||
: k(pg.k), dk_gr(pg.dk_gr), rank(pg.rank), im_rank(pg.im_rank)
|
||||
{ }
|
||||
~sseq_page () { }
|
||||
|
||||
bool operator == (const sseq_page &pg) const { return rank == pg.rank && im_rank == pg.im_rank; }
|
||||
bool equal_as_spaces (const sseq_page &pg) const { return rank == pg.rank; }
|
||||
bool operator == (const sseq_page &pg) const
|
||||
{
|
||||
return k == pg.k
|
||||
&& dk_gr == pg.dk_gr
|
||||
&& rank == pg.rank
|
||||
&& im_rank == pg.im_rank;
|
||||
}
|
||||
|
||||
bool operator != (const sseq_page &pg) const { return !operator == (pg); }
|
||||
|
||||
unsigned total_rank () const;
|
||||
multivariate_laurentpoly<Z> poincare_polynomial (const sseq_bounds &b) const;
|
||||
@ -64,7 +100,7 @@ class sseq_page
|
||||
const sseq_bounds &b1, const sseq_page &pg1,
|
||||
const sseq_bounds &b2, const sseq_page &pg2);
|
||||
|
||||
void texshow (FILE *fp, const sseq_bounds &b, unsigned dh, bool last);
|
||||
template<class M> void texshow (FILE *fp, const sseq_bounds &b, const char *label, M m);
|
||||
};
|
||||
|
||||
class sseq
|
||||
@ -75,8 +111,10 @@ class sseq
|
||||
|
||||
public:
|
||||
sseq () { }
|
||||
sseq (const sseq_bounds &b, const basedvector<sseq_page, 1> &pages_)
|
||||
: bounds(b), pages(pages_)
|
||||
sseq (const sseq_bounds &b,
|
||||
const basedvector<sseq_page, 1> &pages_)
|
||||
: bounds(b),
|
||||
pages(pages_)
|
||||
{ }
|
||||
sseq (const sseq_bounds &b)
|
||||
: bounds(b)
|
||||
@ -84,7 +122,12 @@ class sseq
|
||||
sseq (const sseq &ss) : bounds(ss.bounds), pages(ss.pages) { }
|
||||
~sseq () { }
|
||||
|
||||
sseq &operator = (const sseq &ss) { bounds = ss.bounds; pages = ss.pages; return *this; }
|
||||
sseq &operator = (const sseq &ss)
|
||||
{
|
||||
bounds = ss.bounds;
|
||||
pages = ss.pages;
|
||||
return *this;
|
||||
}
|
||||
|
||||
sseq operator + (const sseq &ss2) const; // direct sum
|
||||
sseq otimes (const sseq &ss2) const; // tensor product
|
||||
@ -95,279 +138,157 @@ class sseq
|
||||
unsigned homological_width () const { return pages[1].homological_width (bounds); }
|
||||
|
||||
bool operator == (const sseq &ss) const { return bounds == ss.bounds && pages == ss.pages; }
|
||||
bool equal_as_spaces (const sseq &ss) const;
|
||||
bool operator != (const sseq &ss) const { return !operator == (ss); }
|
||||
|
||||
void texshow (FILE *fp, std::string name);
|
||||
template<class M> void texshow (FILE *fp, M m);
|
||||
};
|
||||
|
||||
template<class R> class simplified_complex_generators
|
||||
template<class R, class M>
|
||||
sseq_page::sseq_page (const sseq_bounds &b,
|
||||
unsigned k_,
|
||||
grading dk_gr_,
|
||||
mod_map<R> dk,
|
||||
M m)
|
||||
: k(k_),
|
||||
dk_gr(dk_gr_),
|
||||
rank(b.width ()),
|
||||
im_rank(b.width ())
|
||||
{
|
||||
unsigned new_n;
|
||||
ptr<const module<R> > C;
|
||||
basedvector<unsigned, 1> new_C_to_C_generator;
|
||||
dk.check_grading (dk_gr);
|
||||
|
||||
public:
|
||||
simplified_complex_generators (const simplified_complex_generators &g)
|
||||
: new_n(g.new_n),
|
||||
C(g.C),
|
||||
new_C_to_C_generator(g.new_C_to_C_generator)
|
||||
{ }
|
||||
simplified_complex_generators (unsigned new_n_,
|
||||
ptr<const module<R> > C_,
|
||||
basedvector<unsigned, 1> new_C_to_C_generator_)
|
||||
: new_n(new_n_),
|
||||
C(C_),
|
||||
new_C_to_C_generator(new_C_to_C_generator_)
|
||||
{ }
|
||||
~simplified_complex_generators () { }
|
||||
grading m_dk_gr = m.map_delta(dk_gr);
|
||||
|
||||
simplified_complex_generators &operator = (const simplified_complex_generators &); // doesn't exist
|
||||
|
||||
unsigned dim () const { return new_n; }
|
||||
unsigned free_rank () const { return new_n; }
|
||||
grading generator_grading (unsigned i) const { return C->generator_grading (new_C_to_C_generator[i]); }
|
||||
void show_generator (unsigned i) const { C->show_generator (new_C_to_C_generator[i]); }
|
||||
R generator_ann (unsigned i) const { abort (); }
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class chain_complex_simplifier
|
||||
{
|
||||
public:
|
||||
typedef typename R::linear_combination linear_combination;
|
||||
typedef typename R::linear_combination_const_iter linear_combination_const_iter;
|
||||
|
||||
public:
|
||||
ptr<const module<R> > C;
|
||||
unsigned n; // |C|
|
||||
const mod_map<R> &d;
|
||||
|
||||
ptr<const module<R> > new_C;
|
||||
mod_map<R> new_d;
|
||||
|
||||
// chain homotopy equivalences
|
||||
// pi : C -> new_C, iota : new_C -> C
|
||||
mod_map<R> pi, iota;
|
||||
|
||||
private:
|
||||
basedvector<linear_combination, 1> new_d0;
|
||||
basedvector<set<unsigned>, 1> preim;
|
||||
|
||||
bool build_pi_iota;
|
||||
mod_map<R> pi0, iota0;
|
||||
set<unsigned> canceled;
|
||||
|
||||
void cancel (unsigned i, R b, unsigned j);
|
||||
|
||||
public:
|
||||
chain_complex_simplifier (ptr<const module<R> > C_,
|
||||
const mod_map<R> &d_,
|
||||
int dh,
|
||||
bool build_pi_iota_ = 0);
|
||||
|
||||
};
|
||||
|
||||
template<class R> void
|
||||
chain_complex_simplifier<R>::cancel (unsigned i, R b, unsigned j)
|
||||
{
|
||||
assert (i != j);
|
||||
assert (b.is_unit ());
|
||||
|
||||
R binv = b.recip ();
|
||||
|
||||
canceled.push (i);
|
||||
canceled.push (j);
|
||||
|
||||
new_d0[i].yank (j);
|
||||
preim[j].yank (i);
|
||||
|
||||
for (linear_combination_const_iter k = new_d0[i]; k; k ++)
|
||||
preim[k.key ()].yank (i);
|
||||
for (set_const_iter<unsigned> k = preim[i]; k; k ++)
|
||||
new_d0[k.val ()].yank (i);
|
||||
for (linear_combination_const_iter k = new_d0[j]; k; k ++)
|
||||
preim[k.key ()].yank (j);
|
||||
|
||||
if (build_pi_iota)
|
||||
for (unsigned i = 0; i < b.width (); i ++)
|
||||
{
|
||||
mod_map<R> local_pi0 (C, 1),
|
||||
local_iota0 (C, 1);
|
||||
vector<unsigned> r (b.height ()),
|
||||
im_r (b.height ());
|
||||
for (unsigned j = 0; j < b.height (); j ++)
|
||||
r[j] = im_r[j] = 0;
|
||||
|
||||
local_pi0[i].clear ();
|
||||
local_pi0[j].clear ();
|
||||
|
||||
local_iota0[i].clear ();
|
||||
local_iota0[j].clear ();
|
||||
|
||||
for (linear_combination_const_iter ll = new_d0[i]; ll; ll ++)
|
||||
{
|
||||
R c = ll.val ();
|
||||
local_pi0[j].mulsub (binv * c, ll.key ());
|
||||
}
|
||||
|
||||
for (set_const_iter<unsigned> kk = preim[j]; kk; kk ++)
|
||||
{
|
||||
unsigned k = kk.val ();
|
||||
R a = new_d0[k](j);
|
||||
assert (a != 0);
|
||||
|
||||
local_iota0[k].mulsub (a * binv, i);
|
||||
}
|
||||
|
||||
pi0 = local_pi0.compose (pi0);
|
||||
iota0 = iota0.compose (local_iota0);
|
||||
rank[i] = r;
|
||||
im_rank[i] = im_r;
|
||||
}
|
||||
|
||||
for (set_const_iter<unsigned> kk = preim[j]; kk; kk ++)
|
||||
ptr<const module<R> > C = dk.domain ();
|
||||
for (unsigned i = 1; i <= C->dim (); i ++)
|
||||
{
|
||||
unsigned k = kk.val ();
|
||||
R a = new_d0[k](j);
|
||||
assert (a != 0);
|
||||
|
||||
R abinv = a * binv;
|
||||
|
||||
for (linear_combination_const_iter ll = new_d0[i]; ll; ll ++)
|
||||
{
|
||||
unsigned ell = ll.key ();
|
||||
R c = ll.val ();
|
||||
|
||||
assert (! (canceled % k));
|
||||
assert (! (canceled % ell));
|
||||
assert (k != i);
|
||||
assert (k != j);
|
||||
assert (ell != i);
|
||||
assert (ell != j);
|
||||
assert (ell != k);
|
||||
|
||||
new_d0[k].mulsub (abinv * c, ell);
|
||||
if (new_d0[k] % ell)
|
||||
preim[ell] += k;
|
||||
else
|
||||
preim[ell] -= k;
|
||||
}
|
||||
grading gr = m(C->generator_grading (i));
|
||||
rank[(unsigned)(gr.h - b.minh)][(unsigned)(gr.q - b.minq)] ++;
|
||||
}
|
||||
|
||||
for (set_const_iter<unsigned> k = preim[j]; k; k ++)
|
||||
new_d0[k.val ()].yank (j);
|
||||
|
||||
new_d0[i].clear ();
|
||||
preim[i].clear ();
|
||||
new_d0[j].clear ();
|
||||
preim[j].clear ();
|
||||
|
||||
#if 0 // expensive
|
||||
if (build_pi_iota)
|
||||
ptr<const free_submodule<R> > im = dk.image ();
|
||||
for (unsigned i = 1; i <= im->dim (); i ++)
|
||||
{
|
||||
assert (pi0.compose (d) == new_d0.compose (pi0));
|
||||
assert (iota0.compose (new_d0) == d.compose (iota0));
|
||||
grading gr = m(im->generator_grading (i));
|
||||
im_rank[(unsigned)(gr.h - m_dk_gr.h - b.minh)][(unsigned)(gr.q - m_dk_gr.q - b.minq)] ++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class R>
|
||||
chain_complex_simplifier<R>::chain_complex_simplifier (ptr<const module<R> > C_,
|
||||
const mod_map<R> &d_,
|
||||
int dh,
|
||||
bool build_pi_iota_)
|
||||
: C(C_), n(C_->dim ()), d(d_),
|
||||
new_d0(COPY2, d_.explicit_columns ()),
|
||||
preim(C_->dim ()),
|
||||
build_pi_iota(build_pi_iota_)
|
||||
|
||||
template<class M> void
|
||||
sseq_page::texshow (FILE *fp, const sseq_bounds &b, const char *label, M m)
|
||||
{
|
||||
grading m_dk_gr = m.map_delta(dk_gr);
|
||||
|
||||
unsigned dh = m_dk_gr.h,
|
||||
dq = m_dk_gr.q;
|
||||
|
||||
fprintf (fp, "\
|
||||
\\begin{tikzpicture}[scale=.66]\n\
|
||||
\\draw[->] (0,0) -- (%d.5,0) node[right] {$t$};\n\
|
||||
\\draw[->] (0,0) -- (0,%d.5) node[above] {$q$};\n\
|
||||
\\draw[step=1] (0,0) grid (%d,%d);\n",
|
||||
b.width (), b.height (), b.width (), b.height ());
|
||||
|
||||
fprintf (fp, " \\draw (%.3f,-0.8) node[below] {%s};\n",
|
||||
((double)b.width () + 0.5) / 2, label);
|
||||
|
||||
/* label axes */
|
||||
for (int x = b.minh; x <= b.maxh; x ++)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\draw (%d.5,-.2) node[below] {$",
|
||||
x - b.minh);
|
||||
m.x_label (fp, x);
|
||||
fprintf (fp, "$};\n");
|
||||
}
|
||||
for (int y = b.minq; y <= b.maxq; y ++)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\draw (-.2,%d.5) node[left] {$",
|
||||
y - b.minq);
|
||||
m.y_label (fp, y);
|
||||
fprintf (fp, "$};\n");
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < b.width (); i ++)
|
||||
for (unsigned j = 0; j < b.height (); j ++)
|
||||
{
|
||||
int r = rank[i][j];
|
||||
if (r == 1)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\fill (%d.5, %d.5) circle (.15);\n",
|
||||
i, j);
|
||||
}
|
||||
else if (r > 1)
|
||||
{
|
||||
fprintf (fp, "\
|
||||
\\draw (%d.5, %d.5) node {$%d$};\n",
|
||||
i, j, r);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < b.width (); i ++)
|
||||
for (unsigned j = 0; j < b.height (); j ++)
|
||||
{
|
||||
unsigned r = im_rank[i][j];
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
int dx = dh,
|
||||
dy = dq; // in "boxes"
|
||||
|
||||
double h = sqrt ((double)(dx * dx + dy * dy));
|
||||
double xadj = (double)dx / h * 0.3;
|
||||
double yadj = (double)dy / h * 0.3;
|
||||
|
||||
fprintf (fp, " \\draw[->] (%.3f, %.3f) -- ",
|
||||
(double)i + 0.5 + xadj, (double)j + 0.5 + yadj);
|
||||
if (r > 1)
|
||||
fprintf (fp, "node[color=red!75!black] {$%d$} ", r);
|
||||
fprintf (fp, "(%.3f, %.3f);\n",
|
||||
(double)((int)i + dx) + 0.5 - xadj, (double)((int)j + dy) + 0.5 - yadj);
|
||||
}
|
||||
|
||||
fprintf (fp, "\
|
||||
\\end{tikzpicture}\n");
|
||||
|
||||
fflush (fp);
|
||||
}
|
||||
|
||||
template<class M> void
|
||||
sseq::texshow (FILE *fp, M m)
|
||||
{
|
||||
unsigned n = pages.size ();
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
{
|
||||
for (linear_combination_const_iter j = d[i]; j; j ++)
|
||||
preim[j.key ()].push (i);
|
||||
if (i == n)
|
||||
fprintf (fp, "$\\rank E_\\infty = \\rank E_%d = %d$ \\\\\n",
|
||||
pages[i].k, pages[i].total_rank ());
|
||||
else
|
||||
fprintf (fp, "$\\rank E_%d = %d$ \\\\\n",
|
||||
pages[i].k, pages[i].total_rank ());
|
||||
}
|
||||
|
||||
if (build_pi_iota)
|
||||
for (unsigned i = 1; i <= n; i ++)
|
||||
{
|
||||
pi0 = mod_map<R> (C, 1);
|
||||
iota0 = mod_map<R> (C, 1);
|
||||
|
||||
#if 0 // expensive
|
||||
assert (pi0.compose (d) == new_d0.compose (pi0));
|
||||
assert (iota0.compose (new_d0) == d.compose (iota0));
|
||||
#endif
|
||||
}
|
||||
|
||||
Lretry:
|
||||
for (unsigned i = n; i >= 1; i --)
|
||||
{
|
||||
if (canceled % i)
|
||||
continue;
|
||||
|
||||
grading igr = C->generator_grading (i);
|
||||
for (linear_combination_const_iter j = new_d0[i]; j; j ++)
|
||||
{
|
||||
grading jgr = C->generator_grading (j.key ());
|
||||
assert (jgr.h >= igr.h);
|
||||
if (j.val ().is_unit ()
|
||||
&& jgr.h - igr.h == dh)
|
||||
{
|
||||
cancel (i, j.val (), j.key ());
|
||||
goto Lretry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned new_n = n - canceled.card ();
|
||||
basedvector<unsigned, 1> new_C_to_C_generator (new_n),
|
||||
C_to_new_C_generator (n);
|
||||
for (unsigned i = 1, j = 1; i <= n; i ++)
|
||||
{
|
||||
if (canceled % i)
|
||||
{
|
||||
C_to_new_C_generator[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
C_to_new_C_generator[i] = j;
|
||||
new_C_to_C_generator[j] = i;
|
||||
j ++;
|
||||
}
|
||||
|
||||
new_C = (new base_module<R, simplified_complex_generators<R> >
|
||||
(simplified_complex_generators<R> (new_n, C, new_C_to_C_generator)));
|
||||
new_d = mod_map<R> (new_C);
|
||||
|
||||
for (unsigned i = 1; i <= new_n; i ++)
|
||||
{
|
||||
unsigned i0 = new_C_to_C_generator[i];
|
||||
|
||||
for (linear_combination_const_iter j0 = new_d0[i0]; j0; j0 ++)
|
||||
{
|
||||
unsigned j = C_to_new_C_generator[j0.key ()];
|
||||
assert (j != 0);
|
||||
|
||||
new_d[i].muladd (j0.val (), j);
|
||||
}
|
||||
}
|
||||
|
||||
if (build_pi_iota)
|
||||
{
|
||||
pi = mod_map<R> (C, new_C);
|
||||
iota = mod_map<R> (new_C, C);
|
||||
|
||||
for (unsigned i0 = 1; i0 <= n; i0 ++)
|
||||
{
|
||||
for (linear_combination_const_iter j0 = pi0[i0]; j0; j0 ++)
|
||||
{
|
||||
unsigned j = C_to_new_C_generator[j0.key ()];
|
||||
pi[i0].muladd (j0.val (), j);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i <= new_n; i ++)
|
||||
{
|
||||
unsigned i0 = new_C_to_C_generator[i];
|
||||
iota[i] = iota0[i0];
|
||||
}
|
||||
|
||||
#if 0 // expensive
|
||||
assert (pi.compose (d) == new_d.compose (pi));
|
||||
assert (d.compose (iota) == iota.compose (new_d));
|
||||
#endif
|
||||
char buf[1000];
|
||||
if (i == n)
|
||||
sprintf (buf, "$E_\\infty = E_{%d}$", pages[i].k);
|
||||
else
|
||||
sprintf (buf, "$E_{%d}$", pages[i].k);
|
||||
pages[i].texshow (fp, bounds, buf, m);
|
||||
}
|
||||
}
|
||||
|
||||
|
547
steenrod_square.cpp
Normal file
547
steenrod_square.cpp
Normal file
@ -0,0 +1,547 @@
|
||||
|
||||
#include <knotkit.h>
|
||||
|
||||
steenrod_square::steenrod_square (const cube<Z2> &cor_,
|
||||
mod_map<Z2> &d_,
|
||||
const chain_complex_simplifier<Z2> &s_)
|
||||
: cor(cor_), d(d_), s(s_)
|
||||
{
|
||||
for (unsigned i = 1; i <= cor.khC->dim (); i ++)
|
||||
{
|
||||
grading igr = cor.khC->generator_grading (i);
|
||||
KGij[igr].push (i);
|
||||
}
|
||||
}
|
||||
|
||||
Z2
|
||||
steenrod_square::sC (unsigned x, unsigned y) const
|
||||
{
|
||||
pair<unsigned, unsigned> x_sm = cor.generator_state_monomial (x),
|
||||
y_sm = cor.generator_state_monomial (y);
|
||||
|
||||
unsigned changed = x_sm.first ^ y_sm.first;
|
||||
assert (unsigned_bitcount (changed) == 1);
|
||||
unsigned i = unsigned_ffs (changed);
|
||||
|
||||
unsigned k = 0;
|
||||
for (unsigned j = 1; j < i; j ++)
|
||||
{
|
||||
if (unsigned_bittest (x_sm.first, j))
|
||||
k ++;
|
||||
}
|
||||
|
||||
return Z2 (k);
|
||||
}
|
||||
|
||||
Z2
|
||||
steenrod_square::fC (unsigned x, unsigned y) const
|
||||
{
|
||||
pair<unsigned, unsigned> x_sm = cor.generator_state_monomial (x),
|
||||
y_sm = cor.generator_state_monomial (y);
|
||||
|
||||
unsigned changed = x_sm.first ^ y_sm.first;
|
||||
assert (unsigned_bitcount (changed) == 2);
|
||||
|
||||
unsigned i = unsigned_ffs (changed),
|
||||
j = unsigned_ffs (unsigned_bitclear (changed, i));
|
||||
assert (i < j);
|
||||
|
||||
unsigned ki = 0;
|
||||
for (unsigned l = 1; l < i; l ++)
|
||||
{
|
||||
if (unsigned_bittest (x_sm.first, l))
|
||||
ki ++;
|
||||
}
|
||||
unsigned kj = 0;
|
||||
for (unsigned l = i + 1; l < j; l ++)
|
||||
{
|
||||
if (unsigned_bittest (x_sm.first, l))
|
||||
kj ++;
|
||||
}
|
||||
|
||||
return Z2 (ki) * Z2 (kj);
|
||||
}
|
||||
|
||||
triple<set<unsigned>, // G1cx
|
||||
map<unsigned, unsigned>, // bx
|
||||
map<unsigned, Z2> > // sx
|
||||
steenrod_square::boundary_matching (grading cgr,
|
||||
linear_combination<Z2> c,
|
||||
unsigned x) const
|
||||
{
|
||||
set<unsigned> G1cx;
|
||||
map<unsigned, unsigned> bx;
|
||||
map<unsigned, Z2> sx;
|
||||
|
||||
for (linear_combination_const_iter<Z2> yy = c; yy; yy ++)
|
||||
{
|
||||
assert (yy.val () == 1);
|
||||
unsigned y = yy.key ();
|
||||
|
||||
if (d[y](x) == 1)
|
||||
G1cx.push (y);
|
||||
}
|
||||
assert (is_even (G1cx.card ()));
|
||||
|
||||
for (set_const_iter<unsigned> i = G1cx; i; i ++)
|
||||
{
|
||||
unsigned y = i.val ();
|
||||
i ++;
|
||||
unsigned bxy = i.val ();
|
||||
|
||||
bx.push (y, bxy);
|
||||
bx.push (bxy, y);
|
||||
|
||||
sx.push (y, 0);
|
||||
sx.push (bxy, Z2 (1) + sC (x, y) + sC (x, bxy));
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (set_const_iter<unsigned> yy = G1cx; yy; yy ++)
|
||||
{
|
||||
unsigned y = yy.val ();
|
||||
assert (sx(y) + sx(bx(y)) == Z2 (1) + sC (x, y) + sC (x, bx(y)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return triple<set<unsigned>, // G1cx
|
||||
map<unsigned, unsigned>, // bx
|
||||
map<unsigned, Z2> > // sx
|
||||
(G1cx, bx, sx);
|
||||
}
|
||||
|
||||
mod_map<Z2>
|
||||
steenrod_square::sq1 () const
|
||||
{
|
||||
map_builder<Z2> b (s.new_C);
|
||||
|
||||
for (unsigned i = 1; i <= s.new_C->dim (); i ++)
|
||||
{
|
||||
grading cgr = s.new_C->generator_grading (i);
|
||||
linear_combination<Z2> c = s.iota[i];
|
||||
assert (d.map (c) == 0);
|
||||
|
||||
grading gr2 (cgr.h + 1, cgr.q);
|
||||
if (! (KGij % gr2))
|
||||
continue;
|
||||
|
||||
linear_combination<Z2> sq1c (cor.khC);
|
||||
|
||||
for (set_const_iter<unsigned> x = KGij[gr2]; x; x ++)
|
||||
{
|
||||
triple<set<unsigned>,
|
||||
map<unsigned, unsigned>,
|
||||
map<unsigned, Z2> > t = boundary_matching (cgr, c, x.val ());
|
||||
|
||||
Z2 a = 0;
|
||||
for (set_const_iter<unsigned> y = t.first; y; y ++)
|
||||
a += t.third(y.val ());
|
||||
|
||||
sq1c.muladd (a, x.val ());
|
||||
}
|
||||
// display ("sq1c:\n", sq1c);
|
||||
assert (d.map (sq1c) == 0);
|
||||
|
||||
b[i].muladd (1, s.pi.map (sq1c));
|
||||
}
|
||||
|
||||
return mod_map<Z2> (b);
|
||||
}
|
||||
|
||||
set<pair<unsigned, unsigned> >
|
||||
steenrod_square::make_G2cx (grading cgr,
|
||||
linear_combination<Z2> c,
|
||||
unsigned x) const
|
||||
{
|
||||
set<pair<unsigned, unsigned> > G2cx;
|
||||
|
||||
for (linear_combination_const_iter<Z2> yy = c; yy; yy ++)
|
||||
{
|
||||
unsigned y = yy.key ();
|
||||
|
||||
for (linear_combination_const_iter<Z2> zz = d[y]; zz; zz ++)
|
||||
{
|
||||
unsigned z = zz.key ();
|
||||
|
||||
if (d[z](x) == 1)
|
||||
G2cx.push (pair<unsigned, unsigned> (z, y));
|
||||
}
|
||||
}
|
||||
return G2cx;
|
||||
}
|
||||
|
||||
class graph
|
||||
{
|
||||
public:
|
||||
unsigned n_vertices;
|
||||
unsigned n_edges;
|
||||
|
||||
basedvector<unsigned, 1> z;
|
||||
basedvector<unsigned, 1> y;
|
||||
map<pair<unsigned, unsigned>, unsigned> zy_vertex;
|
||||
|
||||
unsigned vertex (unsigned z, unsigned y) const
|
||||
{
|
||||
return zy_vertex(pair<unsigned, unsigned> (z, y));
|
||||
}
|
||||
|
||||
basedvector<unsigned, 1> edge_from, edge_to;
|
||||
set<unsigned> edge_oriented;
|
||||
basedvector<Z2, 1> edge_label;
|
||||
|
||||
map<unsigned, set<unsigned> > incident_edges;
|
||||
|
||||
public:
|
||||
graph (set<pair<unsigned, unsigned> > G2cx);
|
||||
~graph () { }
|
||||
|
||||
void add_edge (unsigned from_z, unsigned from_y,
|
||||
unsigned to_z, unsigned to_y,
|
||||
Z2 label,
|
||||
bool oriented);
|
||||
|
||||
unsigned num_components () const;
|
||||
Z2 f () const; // sum of weights
|
||||
Z2 g () const;
|
||||
};
|
||||
|
||||
graph::graph (set<pair<unsigned, unsigned> > G2cx)
|
||||
: n_vertices(G2cx.card ()),
|
||||
n_edges(0),
|
||||
z(n_vertices),
|
||||
y(n_vertices)
|
||||
{
|
||||
unsigned j = 1;
|
||||
for (set_const_iter<pair<unsigned, unsigned> > i = G2cx; i; i ++, j ++)
|
||||
{
|
||||
z[j] = i.val ().first;
|
||||
y[j] = i.val ().second;
|
||||
zy_vertex.push (i.val (), j);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
for (unsigned i = 1; i <= n_vertices; i ++)
|
||||
{
|
||||
assert (i == vertex (z[i], y[i]));
|
||||
}
|
||||
#endif
|
||||
assert (j == n_vertices + 1);
|
||||
}
|
||||
|
||||
void
|
||||
graph::add_edge (unsigned from_z, unsigned from_y,
|
||||
unsigned to_z, unsigned to_y,
|
||||
Z2 label,
|
||||
bool oriented)
|
||||
{
|
||||
unsigned e = ++ n_edges;
|
||||
|
||||
unsigned from = vertex (from_z, from_y),
|
||||
to = vertex (to_z, to_y);
|
||||
|
||||
edge_from.append (from);
|
||||
edge_to.append (to);
|
||||
edge_label.append (label);
|
||||
assert (e == edge_label.size ());
|
||||
|
||||
if (oriented)
|
||||
edge_oriented.push (e);
|
||||
|
||||
incident_edges[from].push (e);
|
||||
incident_edges[to].push (e);
|
||||
}
|
||||
|
||||
unsigned
|
||||
graph::num_components () const
|
||||
{
|
||||
unionfind<1> u (n_vertices);
|
||||
for (unsigned i = 1; i <= n_edges; i ++)
|
||||
u.join (edge_from[i], edge_to[i]);
|
||||
return u.num_sets ();
|
||||
}
|
||||
|
||||
Z2
|
||||
graph::f () const
|
||||
{
|
||||
Z2 a = 0;
|
||||
for (unsigned i = 1; i <= n_edges; i ++)
|
||||
a += edge_label[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
Z2
|
||||
graph::g () const
|
||||
{
|
||||
set<unsigned> done;
|
||||
|
||||
set<unsigned> A,
|
||||
B;
|
||||
for (unsigned i = 1; i <= n_edges; i ++)
|
||||
{
|
||||
if (done % i)
|
||||
continue;
|
||||
|
||||
unsigned j = i;
|
||||
unsigned v = edge_to[j];
|
||||
for (;;)
|
||||
{
|
||||
if (edge_oriented % j)
|
||||
{
|
||||
if (edge_to[j] == v)
|
||||
A.push (j);
|
||||
else
|
||||
B.push (j);
|
||||
}
|
||||
done.push (j);
|
||||
|
||||
if (incident_edges[v].head () == j)
|
||||
j = incident_edges[v].tail ();
|
||||
else
|
||||
{
|
||||
assert (j == incident_edges[v].tail ());
|
||||
j = incident_edges[v].head ();
|
||||
}
|
||||
if (v == edge_to[j])
|
||||
v = edge_from[j];
|
||||
else
|
||||
{
|
||||
assert (v == edge_from[j]);
|
||||
v = edge_to[j];
|
||||
}
|
||||
|
||||
if (j == i)
|
||||
{
|
||||
assert (v == edge_to[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (Z2 (A.card ()) == Z2 (B.card ()));
|
||||
return Z2 (A.card ());
|
||||
}
|
||||
|
||||
pair<set<unsigned>,
|
||||
map<unsigned, unsigned> >
|
||||
steenrod_square::ladybug_matching (unsigned x, unsigned y) const
|
||||
{
|
||||
set<unsigned> Gxy;
|
||||
map<unsigned, unsigned> lxy;
|
||||
|
||||
for (linear_combination_const_iter<Z2> zz = d[y]; zz; zz ++)
|
||||
{
|
||||
unsigned z = zz.key ();
|
||||
|
||||
if (d[z](x) == 1)
|
||||
Gxy.push (z);
|
||||
}
|
||||
|
||||
if (Gxy.card () == 2)
|
||||
{
|
||||
unsigned z1 = Gxy.head (),
|
||||
z2 = Gxy.tail ();
|
||||
assert (z1 != z2);
|
||||
|
||||
lxy.push (z1, z2);
|
||||
lxy.push (z2, z1);
|
||||
}
|
||||
else if (Gxy.card () == 4)
|
||||
{
|
||||
pair<unsigned, unsigned> x_sm = cor.generator_state_monomial (x),
|
||||
y_sm = cor.generator_state_monomial (y);
|
||||
|
||||
unsigned changed = x_sm.first ^ y_sm.first;
|
||||
assert (unsigned_bitcount (changed) == 2);
|
||||
unsigned i = unsigned_ffs (changed),
|
||||
j = unsigned_ffs (unsigned_bitclear (changed, i));
|
||||
|
||||
unsigned s00 = y_sm.first;
|
||||
unsigned s01 = unsigned_bitset (s00, i);
|
||||
unsigned s10 = unsigned_bitset (s00, j);
|
||||
|
||||
smoothing from_s (cor.kd, smallbitset (cor.n_crossings, s00));
|
||||
|
||||
basedvector<unsigned, 1> from_circle_edge_rep (from_s.n_circles);
|
||||
for (unsigned j = 1; j <= cor.kd.num_edges (); j ++)
|
||||
from_circle_edge_rep[from_s.edge_circle[j]] = j;
|
||||
|
||||
unsigned e1 = cor.kd.ept_edge (cor.kd.crossings[i][1]),
|
||||
e3 = cor.kd.ept_edge (cor.kd.crossings[i][3]);
|
||||
|
||||
unsigned p = from_s.edge_circle[e1];
|
||||
assert (p == from_s.edge_circle[e3]);
|
||||
assert (unsigned_bittest (y_sm.second, p)); // p+
|
||||
|
||||
smoothing conf01 (cor.kd, smallbitset (cor.n_crossings, s01)),
|
||||
conf10 (cor.kd, smallbitset (cor.n_crossings, s10));
|
||||
|
||||
assert (conf01.edge_circle[e1] != conf01.edge_circle[e3]);
|
||||
assert (conf10.edge_circle[e1] != conf10.edge_circle[e3]);
|
||||
|
||||
unsigned m01 = 0,
|
||||
m10 = 0;
|
||||
for (unsigned i = 1; i <= from_s.n_circles; i ++)
|
||||
{
|
||||
if (unsigned_bittest (y_sm.second, i))
|
||||
{
|
||||
m01 = unsigned_bitset (m01, conf01.edge_circle[from_circle_edge_rep[i]]);
|
||||
m10 = unsigned_bitset (m10, conf10.edge_circle[from_circle_edge_rep[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned m01_a = unsigned_bitclear (unsigned_bitset (m01,
|
||||
conf01.edge_circle[e1]),
|
||||
conf01.edge_circle[e3]),
|
||||
m10_a = unsigned_bitclear (unsigned_bitset (m10,
|
||||
conf10.edge_circle[e1]),
|
||||
conf10.edge_circle[e3]);
|
||||
unsigned z01_a = cor.generator (s01, m01_a),
|
||||
z10_a = cor.generator (s10, m10_a);
|
||||
assert (Gxy(z01_a) && Gxy(z10_a));
|
||||
lxy.push (z01_a, z10_a);
|
||||
lxy.push (z10_a, z01_a);
|
||||
|
||||
unsigned m01_b = unsigned_bitclear (unsigned_bitset (m01,
|
||||
conf01.edge_circle[e3]),
|
||||
conf01.edge_circle[e1]),
|
||||
m10_b = unsigned_bitclear (unsigned_bitset (m10,
|
||||
conf10.edge_circle[e3]),
|
||||
conf10.edge_circle[e1]);
|
||||
unsigned z01_b = cor.generator (s01, m01_b),
|
||||
z10_b = cor.generator (s10, m10_b);
|
||||
assert (Gxy(z01_b) && Gxy(z10_b));
|
||||
lxy.push (z01_b, z10_b);
|
||||
lxy.push (z10_b, z01_b);
|
||||
}
|
||||
else
|
||||
assert (Gxy.card () == 0);
|
||||
|
||||
assert (Gxy.card () == lxy.card ());
|
||||
|
||||
return pair<set<unsigned>, map<unsigned, unsigned> > (Gxy, lxy);
|
||||
}
|
||||
|
||||
Z2
|
||||
steenrod_square::sq2_coeff (grading cgr,
|
||||
linear_combination<Z2> c,
|
||||
unsigned x) const
|
||||
{
|
||||
set<pair<unsigned, unsigned> > G2cx = make_G2cx (cgr, c, x);
|
||||
|
||||
graph G (G2cx);
|
||||
|
||||
set<unsigned> ys;
|
||||
for (unsigned i = 1; i <= G.n_vertices; i ++)
|
||||
ys += G.y[i];
|
||||
|
||||
for (set_const_iter<unsigned> yy = ys; yy; yy ++)
|
||||
{
|
||||
unsigned y = yy.val ();
|
||||
|
||||
pair<set<unsigned>,
|
||||
map<unsigned, unsigned> > p = ladybug_matching (x, y);
|
||||
|
||||
set<unsigned> Gxy = p.first;
|
||||
map<unsigned, unsigned> lxy = p.second;
|
||||
|
||||
for (set_const_iter<unsigned> zz = Gxy; zz; zz ++)
|
||||
{
|
||||
unsigned z = zz.val ();
|
||||
unsigned lxyz = lxy(z);
|
||||
if (z < lxyz)
|
||||
{
|
||||
G.add_edge (z, y,
|
||||
lxyz, y,
|
||||
fC (x, y), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set<unsigned> zs;
|
||||
for (unsigned i = 1; i <= G.n_vertices; i ++)
|
||||
zs += G.z[i];
|
||||
|
||||
for (set_const_iter<unsigned> zz = zs; zz; zz ++)
|
||||
{
|
||||
unsigned z = zz.val ();
|
||||
triple<set<unsigned>,
|
||||
map<unsigned, unsigned>,
|
||||
map<unsigned, Z2> > t = boundary_matching (cgr, c, z);
|
||||
|
||||
set<unsigned> Gcz = t.first;
|
||||
map<unsigned, unsigned> bz = t.second;
|
||||
map<unsigned, Z2> sz = t.third;
|
||||
|
||||
for (set_const_iter<unsigned> yy = Gcz; yy; yy ++)
|
||||
{
|
||||
unsigned y = yy.val ();
|
||||
|
||||
unsigned bzy = bz(y);
|
||||
if (y < bzy)
|
||||
{
|
||||
if (sz(y) == 0
|
||||
&& sz(bzy) == 1)
|
||||
{
|
||||
G.add_edge (z, y,
|
||||
z, bzy,
|
||||
0, 1);
|
||||
}
|
||||
else if (sz(y) == 1
|
||||
&& sz(bzy) == 0)
|
||||
{
|
||||
G.add_edge (z, bzy,
|
||||
z, y,
|
||||
0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (sz(y) == sz(bzy));
|
||||
G.add_edge (z, y,
|
||||
z, bzy,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (unsigned i = 1; i <= G.n_edges; i ++)
|
||||
{
|
||||
assert (G.incident_edges[i].card () == 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// printf ("G.n_edges = %d\n", G.n_edges);
|
||||
// printf ("#|G| = %d\n", G.num_components ());
|
||||
|
||||
return (Z2 (G.num_components ())
|
||||
+ G.f ()
|
||||
+ G.g ());
|
||||
}
|
||||
|
||||
mod_map<Z2>
|
||||
steenrod_square::sq2 () const
|
||||
{
|
||||
map_builder<Z2> b (s.new_C);
|
||||
|
||||
for (unsigned i = 1; i <= s.new_C->dim (); i ++)
|
||||
{
|
||||
grading cgr = s.new_C->generator_grading (i);
|
||||
linear_combination<Z2> c = s.iota[i];
|
||||
assert (d.map (c) == 0);
|
||||
|
||||
grading gr2 (cgr.h + 2, cgr.q);
|
||||
if (! (KGij % gr2))
|
||||
continue;
|
||||
|
||||
linear_combination<Z2> sq2c (cor.khC);
|
||||
for (set_const_iter<unsigned> x = KGij[gr2]; x; x ++)
|
||||
sq2c.muladd (sq2_coeff (cgr, c, x.val ()), x.val ());
|
||||
|
||||
// display ("sq2c:\n", sq2c);
|
||||
assert (d.map (sq2c) == 0);
|
||||
|
||||
b[i].muladd (1, s.pi.map (sq2c));
|
||||
}
|
||||
|
||||
return mod_map<Z2> (b);
|
||||
}
|
42
steenrod_square.h
Normal file
42
steenrod_square.h
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
class steenrod_square
|
||||
{
|
||||
// cube of resolutions (in steenrod_square, c will denote a cycle)
|
||||
const cube<Z2> &cor;
|
||||
|
||||
mod_map<Z2> d;
|
||||
const chain_complex_simplifier<Z2> &s;
|
||||
|
||||
map<grading, set<unsigned> > KGij;
|
||||
|
||||
// sC, fC take generators as input, not hypercube vertices
|
||||
Z2 sC (unsigned x, unsigned y) const;
|
||||
Z2 fC (unsigned x, unsigned y) const;
|
||||
|
||||
pair<set<unsigned>, // Gxy
|
||||
map<unsigned, unsigned> // lxy
|
||||
> ladybug_matching (unsigned x, unsigned y) const;
|
||||
|
||||
triple<set<unsigned>, // Gcx
|
||||
map<unsigned, unsigned>, // bx
|
||||
map<unsigned, Z2> // sx
|
||||
> boundary_matching (grading cgr,
|
||||
linear_combination<Z2> c,
|
||||
unsigned x) const;
|
||||
|
||||
set<pair<unsigned, unsigned> > make_G2cx (grading cgr,
|
||||
linear_combination<Z2> c,
|
||||
unsigned x) const;
|
||||
Z2 sq2_coeff (grading cgr,
|
||||
linear_combination<Z2> c,
|
||||
unsigned x) const;
|
||||
|
||||
public:
|
||||
steenrod_square (const cube<Z2> &cor_,
|
||||
mod_map<Z2> &d_,
|
||||
const chain_complex_simplifier<Z2> &s_);
|
||||
~steenrod_square () { }
|
||||
|
||||
mod_map<Z2> sq1 () const;
|
||||
mod_map<Z2> sq2 () const;
|
||||
};
|
72
todo.txt
72
todo.txt
@ -13,10 +13,8 @@ in knotkit/
|
||||
deepcopy
|
||||
|
||||
in lib/
|
||||
- add hashset
|
||||
- between interoperation between sets that require bounds (bitset,
|
||||
ullmanset) and those that don't (set, hashset)
|
||||
- add make_pair, etc.
|
||||
|
||||
in algebra/
|
||||
- linear_combnation can be more efficient (eg no searching when
|
||||
@ -25,3 +23,73 @@ in algebra/
|
||||
- cleaner interface for gcd, etc. in fraction_field
|
||||
- support kernel, cokernel of torsion modules
|
||||
- change gcd et al so gcd is always positive
|
||||
- split linear_combination into internal and external versions
|
||||
|
||||
git:
|
||||
- fix bug in Josh's version
|
||||
- make this master, merge into Josh's version
|
||||
- merge in square to master => then write paper!
|
||||
- merge in other improvements (sped up linear algebra? multivariate (laurent) polynomial?)
|
||||
- should exponents on polynomials be Z or unsigned?
|
||||
|
||||
general:
|
||||
- unify simplify_chain_complex, sseq, kernel/image/homology (as much as possible)
|
||||
- sseq over Z
|
||||
- quadratic linear solver (enumerator?)
|
||||
- classes should either COPY or fully SHARE, but not some of each
|
||||
(e.g. knot_diagram, resolution_diagram, etc.) -- this is the right
|
||||
semantics.
|
||||
- clean up/delete setcommon, mapcommon
|
||||
- incorporate sage dump into standard classes
|
||||
- update use of tuples in steenrod square
|
||||
|
||||
- test mutation invariance, other questions of Robert and Sucharit
|
||||
- write paper
|
||||
|
||||
c++11:
|
||||
- make vector wrap std::vector (probably faster)
|
||||
|
||||
- use tuple instead of pair, triple; and use tie, a great idiom
|
||||
- standardize ring, field interface so test_ring works for everything
|
||||
- get clear on default semantics: prefer default when possible
|
||||
|
||||
- standardize use of {} for initializers
|
||||
- initializer_list for container types
|
||||
- support for iterator
|
||||
|
||||
- compress Steenrod square data
|
||||
- get mpimain running again, run 15 xing mutants
|
||||
|
||||
- simplifications to run (5, 8) with symmetries.
|
||||
|
||||
notes:
|
||||
|
||||
all rings (R): multivariate_laurentpoly<R>
|
||||
|
||||
fields (F): Z2 Zp Q fraction_field<E> (for just pids?)
|
||||
|
||||
euclidean domains (E): Z polynomial<F>
|
||||
|
||||
euclidean domain interface:
|
||||
|
||||
num/demon : denom must be a unit
|
||||
= num.operator / (denom)
|
||||
|
||||
denom.divides (num)
|
||||
denom | num
|
||||
|
||||
num.divide_exact (denom)
|
||||
|
||||
(q, r) = num.divide_with_remainder (denom)
|
||||
(q, r) = num / denom
|
||||
(q, r) = num.operator / (denom)
|
||||
satisfies r = 0 or f(r) < f(denom) and num = q*denom + r
|
||||
|
||||
gcd (a, b)
|
||||
lcm (a, b)
|
||||
r = num.mod (denom)
|
||||
satisfies r = 0 or f(r) < f(denom)
|
||||
|
||||
|
||||
(d, s, t) = a.extended_gcd (b)
|
||||
satifies d is the gcd and d = a*s + b*t
|
||||
|
Loading…
Reference in New Issue
Block a user