Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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