Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion M2/BUILD/mike/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ cmake-debug-appleclang:
arm64-appleclang : always
mkdir -p builds.tmp/arm64-appleclang
cd builds.tmp/arm64-appleclang; ../../../../configure \
--enable-dmg \
--enable-download --with-system-gc \
--with-system-memtailor --with-system-mathic \
--with-system-mathicgb \
Expand Down
40 changes: 31 additions & 9 deletions M2/Macaulay2/packages/Complexes/ChainComplex.m2
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Complex = new Type of MutableHashTable --
-- missing ones are presumed to be the zero module.
-- cache: a CacheTable

ComplexMap = new Type of HashTable
ComplexMap = new Type of MutableHashTable
-- keys:
-- degree: ZZ
-- source: Complex over a ring R
Expand Down Expand Up @@ -111,6 +111,27 @@ complex HashTable := Complex => complexOptions >> opts -> maps -> (
C.dd = map(C,C,maps,Degree=>-1);
C
)
complex(HashTable, Function) := Complex => complexOptions >> opts -> (modules, mapfcn) -> (
spots := sort keys modules;
if #spots === 0 then
error "expected at least one module";
if not all(spots, k -> instance(k,ZZ)) then
error "expected modules to be labelled by integers";
if not uniform values modules then
error "expected hash table of modules";
if not same(ring \ values modules) then
error "expected all modules to be over the same ring";
R := ring modules#(spots#0);
C := new Complex from {
symbol ring => R,
-- TODO: rename module to category agnostic term
symbol module => new HashTable from modules,
symbol concentration => (first spots, last spots),
symbol cache => new CacheTable
};
C.dd = map(C, C, mapfcn, 23982138, Degree=>-1); -- the integer grabs the lazy maps version.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

???

C
)
complex List := Complex => complexOptions >> opts -> L -> (
-- L is a list of matrices or a list of modules
if not instance(opts.Base, ZZ) then
Expand Down Expand Up @@ -258,7 +279,12 @@ isWellDefined Complex := Boolean => C -> (
);
return false;
);
if not all(keys (dd^C).map, i -> instance(i,ZZ) and i >= lo+1 and i <= hi) then (
if member(symbol Function, keys (dd^C).map) then (
if debugLevel > 0 then (
<< "-- lazy differential present" << endl;
);
);
if not all(keys (dd^C).map, i -> (i === symbol Function) or (instance(i,ZZ) and i >= lo+1 and i <= hi)) then (
if debugLevel > 0 then (
<< "-- expected all maps in the differential to be indexed by integers in the concentration [lo+1,hi]" << endl;
);
Expand Down Expand Up @@ -292,7 +318,7 @@ isWellDefined Complex := Boolean => C -> (
Module Array := Complex => (M, v) -> (
if length v =!= 1 then error "expected array of length 1";
if class v#0 =!= ZZ then error "expected [n] with n an integer";
complex(M, Base => v#0))
complex(M, Base => -v#0))

Complex _ ZZ := Module => (C,i) -> if C.module#?i then C.module#i else (ring C)^0
Complex ^ ZZ := Module => (C,i) -> C_(-i)
Expand Down Expand Up @@ -792,8 +818,6 @@ truncate(List, Complex) := Complex => truncateModuleOpts >> opts -> (degs, C) ->
(lo, hi) := C.concentration;
if lo == hi
then complex(truncate(degs, C_lo, opts), Base => lo)
-- this is the simplest way to truncate the whole complex:
-- else complex applyValues(C.dd.map, f -> truncate(degs, f, opts)))
else (
-- this construction requires ~half as many truncations
f := truncate(degs, dd^C_lo, opts);
Expand All @@ -814,8 +838,6 @@ basis(List, Complex) := Complex => opts -> (deg, C) -> (
(lo, hi) := C.concentration;
if lo == hi
then complex(image basis(deg, C_lo, opts), Base => lo)
-- this is the simplest way to take the basis of the whole complex:
-- else complex applyValues(C.dd.map, f -> basis(deg, f, opts)))
else (
-- this construction requires ~half as many basis computations
f := basis(deg, dd^C_lo, opts);
Expand All @@ -832,9 +854,9 @@ importFrom_Core "residueMap" -- gives a map back to the coefficient ring
cover' = method()
cover' Complex := Complex => C -> (
(lo, hi) := concentration C;
if lo == hi
if lo === hi
then complex(cover C_lo, Base => lo)
else complex applyValues(C.dd.map, cover))
else complex(for i from lo+1 to hi list cover C.dd_i, Base => lo))
cover' ComplexMap := ComplexMap => f -> (
map(cover' target f, cover' source f, i -> cover f_i, Degree => degree f))

Expand Down
1 change: 0 additions & 1 deletion M2/Macaulay2/packages/Complexes/ChainComplexDoc.m2
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,6 @@ doc ///
get the maps between the terms in a complex
Usage
dd^C
dd_C
Inputs
C:Complex
Outputs
Expand Down
101 changes: 78 additions & 23 deletions M2/Macaulay2/packages/Complexes/ChainComplexMap.m2
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ target ComplexMap := Complex => f -> f.target
ring ComplexMap := Complex => f -> ring source f
degree ComplexMap := ZZ => f -> f.degree

isHomogeneous ComplexMap := (f) -> all(values f.map, isHomogeneous)
isHomogeneous ComplexMap := (f) -> (
(lo, hi) := concentration f;
all(lo..hi, i -> isHomogeneous f_i)
)

map(Complex, Complex, HashTable) := ComplexMap => opts -> (tar, src, maps) -> (
R := ring tar;
Expand Down Expand Up @@ -80,6 +83,7 @@ map(Complex, Complex, List) := ComplexMap => opts -> (tar, src, maps) -> (
map(tar,src,mapHash,opts, Degree=>deg)
)

-- TODO: remove this version
map(Complex, Complex, Function) := ComplexMap => opts -> (D,C,f) -> (
deg := if opts.Degree === null then 0 else opts.Degree;
(loC,hiC) := concentration C;
Expand All @@ -93,6 +97,28 @@ map(Complex, Complex, Function) := ComplexMap => opts -> (D,C,f) -> (
map(D,C,maps,Degree=>deg)
)

-- the integer 4th argument is a hack to try out lazy evaluation of matrices
map(Complex, Complex, Function, ZZ) := ComplexMap => opts -> (tar,src,f,ignored) -> (
deg := if opts.Degree === null then 0 else opts.Degree;
(loSrc,hiSrc) := concentration src;
(loTar,hiTar) := concentration tar;
mapfcn := i -> (
if i < max(loSrc,loTar-deg) or i > min(hiSrc,hiTar-deg) then return null;
if src_i == 0 or tar_(i+deg) == 0 then return null;
g := f i;
if g === null or g == 0 then return null;
g
);
maps := new MutableHashTable from {symbol Function => mapfcn};
new ComplexMap from {
symbol source => src,
symbol target => tar,
symbol degree => deg,
symbol map => maps,
symbol cache => new CacheTable
}
)

map(Complex, Complex, ZZ) := ComplexMap => opts -> (D, C, j) -> (
if j === 0 then (
result := map(D,C,hashTable{},opts);
Expand All @@ -103,10 +129,23 @@ map(Complex, Complex, ZZ) := ComplexMap => opts -> (D, C, j) -> (
return j * id_C;
error "expected 0 or source and target to be the same")

-- map(Complex, Complex, ComplexMap) := ComplexMap => opts -> (tar, src, f) -> (
-- deg := if opts.Degree === null then degree f else opts.Degree;
-- H := hashTable for k in keys f.map list k => map(tar_(deg+k), src_k, f.map#k); -- TODO: fix me
-- map(tar,src,H, Degree=>deg)
-- )

map(Complex, Complex, ComplexMap) := ComplexMap => opts -> (tar, src, f) -> (
deg := if opts.Degree === null then degree f else opts.Degree;
H := hashTable for k in keys f.map list k => map(tar_(deg+k), src_k, f.map#k);
map(tar,src,H, Degree=>deg)
if f.map.?Function then (
-- is lazy
mapfcn := k -> map(tar_(deg+k), src_k, f.map.Function k);
map(tar, src, mapfcn, 324732984, Degree => deg) -- TODO: get rid of magic number
)
else (
H := hashTable for k in keys f.map list k => map(tar_(deg+k), src_k, f.map#k);
map(tar,src,H, Degree=>deg)
)
)

ComplexMap | ComplexMap := ComplexMap => (f,g) -> (
Expand Down Expand Up @@ -170,7 +209,12 @@ isWellDefined ComplexMap := f -> (
return false;
);
(lo,hi) := f.source.concentration;
if not all(keys f.map, i -> instance(i,ZZ) and i >= lo and i <= hi) then (
if member(symbol Function, keys f.map) then (
if debugLevel > 0 then (
<< "-- lazy maps present" << endl;
);
);
if not all(keys f.map, i -> (i === symbol Function) or (instance(i,ZZ) and i >= lo and i <= hi)) then (
if debugLevel > 0 then (
<< "-- expected all maps to be indexed by integers in the concentration [lo,hi] of the source" << endl;
);
Expand Down Expand Up @@ -227,32 +271,43 @@ isWellDefined ComplexMap := f -> (
lineOnTop := (s) -> concatenate(width s : "-") || s

expression ComplexMap := Expression => f -> (
(lo, hi) := concentration f;
d := degree f;
s := sort keys f.map;
if #s === 0 then
new ZeroExpression from {0}
else new VerticalList from for i in s list
new Holder from new VerticalList from for i from lo to hi list
RowExpression {i+d, ":", MapExpression { target f_i, source f_i, f_i }, ":", i}
)

net ComplexMap := Net => f -> (
v := between("",
for i in sort keys f.map list (
horizontalJoin(
net (i+f.degree), " : ", net target f_i, " <--",
lineOnTop net f_i,
"-- ", net source f_i, " : ", net i
)
));
if # v === 0 then net "0"
else stack v
)
(lo, hi) := concentration f;
v := between("",
for i from lo to hi list (
horizontalJoin(
net (i+f.degree), " : ", net target f_i, " <--",
lineOnTop net f_i,
"-- ", net source f_i, " : ", net i
)
));
if # v === 0 then net "0"
else stack v
)

texMath ComplexMap := String => f -> texMath expression f
mathML ComplexMap := String => f -> mathML expression f

-- ComplexMap _ ZZ := Matrix => (f,i) -> (
-- if f.map#?i then f.map#i else map((target f)_(i + degree f), (source f)_i, 0))

ComplexMap _ ZZ := Matrix => (f,i) -> (
if f.map#?i then f.map#i else map((target f)_(i + degree f), (source f)_i, 0))
if f.map#?i then return f.map#i;
if f.map.?Function then (
if debugLevel > 0 then
<< "creating " << i << "-th differential" << endl;
g := f.map.Function i;
if g =!= null then return f.map#i = g
);
map((target f)_(i + degree f), (source f)_i, 0)
)

ComplexMap ^ ZZ := ComplexMap => (f,n) -> (
(lo,hi) := (source f).concentration;
df := degree f;
Expand Down Expand Up @@ -296,12 +351,12 @@ ComplexMap == ComplexMap := (f,g) -> (
true
)
ComplexMap == ZZ := Boolean => (f,n) -> (
if n === 0 then
all(keys f.map, k -> f.map#k == 0)
(lo,hi) := (source f).concentration;
if n === 0 then
all(lo..hi, k -> f_k == 0)
else if n === 1 then (
if source f != target f then return false;
if degree f =!= 0 then return false;
(lo,hi) := (source f).concentration;
for i from lo to hi do
if f_i != 1 then return false;
f.cache.isCommutative = true; -- this is the identity, after all!
Expand Down
16 changes: 8 additions & 8 deletions M2/Macaulay2/packages/Complexes/ChainComplexMapDoc.m2
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ doc ///
Using this function to create the identity map
is the same as using @TO (id, Complex)@.
Example
assert(map(C, C, 1) === id_C)
assert(map(C, C, 1) == id_C)
SeeAlso
ComplexMap
(map, Complex, Complex, Function)
Expand Down Expand Up @@ -871,8 +871,8 @@ doc ///
f = g1 ++ g2
assert isWellDefined f
L = components f
L_0 === g1
L_1 === g2
L_0 == g1
L_1 == g2
indices f
f' = (greg => g1) ++ (mike => g2)
components f'
Expand Down Expand Up @@ -1398,7 +1398,7 @@ doc ///
then the identity map of the corresponding complex is used.
Example
fE = f ** E
assert(fE === f ** id_E)
assert(fE == f ** id_E)
k = coker vars S
gk = g ** k
assert(gk == g ** id_(complex k))
Expand Down Expand Up @@ -2130,7 +2130,7 @@ doc ///
Text
This is really a shorthand for constructing complex maps via block matrices.
Example
assert(h === map(D, C1 ++ C2, {{f,g}}))
assert(h == map(D, C1 ++ C2, {{f,g}}))
SeeAlso
(symbol++, Complex, Complex)
(symbol++, ComplexMap, ComplexMap)
Expand Down Expand Up @@ -2173,7 +2173,7 @@ doc ///
Text
This is really a shorthand for constructing complex maps via block matrices.
Example
assert(h === map(D1 ++ D2, C, {{f},{g}}))
assert(h == map(D1 ++ D2, C, {{f},{g}}))
SeeAlso
(symbol++, Complex, Complex)
(symbol++, ComplexMap, ComplexMap)
Expand Down Expand Up @@ -3485,8 +3485,8 @@ doc ///
f' = map(M, L, 1)
g' = freeResolution f'
g'' = freeResolution(f * f')
assert(g'' === g * g')
assert(freeResolution id_N === id_(freeResolution N))
assert(g'' == g * g')
assert(freeResolution id_N == id_(freeResolution N))
Text
Over a quotient ring, free resolutions are often infinite.
Use the optional argument {\tt LengthLimit} to obtain
Expand Down
59 changes: 59 additions & 0 deletions M2/Macaulay2/packages/Complexes/ChainComplexTests.m2
Original file line number Diff line number Diff line change
Expand Up @@ -2411,3 +2411,62 @@ TEST ///
C9 = constantStrand(C, 9)
assert isWellDefined C9
///

TEST /// -- test of lazy maps in a complex map
R = ZZ/32003[x,y,z]
C = res coker vars R
fC = map(C, C, i -> map(C_i, C_i, 1), 893723834);
assert(keys fC.map === {symbol Function})
assert(fC_1 === fC_1)
assert(fC_1 == 1)
assert(set keys fC.map === set{1, symbol Function})
assert(fC_3 == 1)
assert(set keys fC.map === set{1, 3, symbol Function})
assert(fC_5 == 0)
assert(set keys fC.map === set{1, 3, symbol Function})
assert isWellDefined fC
///

TEST /// -- test construction of complex with lazy differentials.
restart
R = ZZ/32003[x,y,z,w]
C = res coker vars R
assert(keys (dd^C).map === {symbol Function})
assert(C.dd_1 === C.dd_1)
assert(set keys C.dd.map === set{1, symbol Function})
C.dd_3
assert(set keys C.dd.map === set{1, 3, symbol Function})
assert(C.dd_5 == 0)
assert(set keys C.dd.map === set{1, 3, symbol Function})
assert isWellDefined C.dd
assert isWellDefined C

-- now we construct a complex with a lazy differential
modules = hashTable for i from 0 to 4 list i => C_i
mapfcn = i -> C.dd_i
D = complex(modules, mapfcn)
assert(D.concentration === (0,4))
assert(D.ring === R)
assert(D.module === modules)
assert(D.dd.source === D)
assert(D.dd.target === D)
assert(D.dd.degree === -1)
assert(keys D.dd.map === {symbol Function})
assert all(1..4, i -> mapfcn i == D.dd.map.Function i)
assert(keys D.dd.map === {symbol Function})
assert isWellDefined D
///

TEST ///
restart
--needsPackage "OldChainComplexes"
S = ZZ/101[x_1..x_9];
J = ideal vars S;
T = S/J^5;
elapsedTime C = res coker presentation T
debugLevel = 1
elapsedTime C.dd_9;
elapsedTime C.dd_6;
profile (C = res coker presentation T)
profileSummary()
///
Loading
Loading