File: intersection.m2

package info (click to toggle)
macaulay2 1.21%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 133,096 kB
  • sloc: cpp: 110,377; ansic: 16,306; javascript: 4,193; makefile: 3,821; sh: 3,580; lisp: 764; yacc: 590; xml: 177; python: 140; perl: 114; lex: 65; awk: 3
file content (178 lines) | stat: -rw-r--r-- 7,005 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
------------------------------------------------------
-- numerical intersection routines 
-- (loaded by  ../NumericalAlgebraicGeometry.m2)
------------------------------------------------------

export {"hypersurfaceSection", "numericalIntersection"}

insertComponent = method()
insertComponent(WitnessSet,MutableHashTable) := (W,H) -> (
     d := dim W;
     --if H#?d then H#d#(#H) = W -- ??? 
     if H#?d then H#d#(#(H#d)) = W 
     else H#d = new MutableHashTable from {0=>W};
     )

isPointOnAnyComponent = method()
isPointOnAnyComponent(AbstractPoint,HashTable) := (p,H) -> any(keys H, d -> any(keys H#d, k -> isOn(p,H#d#k)))

splitWitness = method(TypicalValue=>Sequence, Options =>{Tolerance=>null})
splitWitness (WitnessSet,RingElement) := Sequence => o -> (w,f) -> (
-- splits the witness set into two parts: one contained in {f=0}, the other not
-- IN:  comp = a witness set
--      f = a polynomial
-- OUT: (w1,w2) = two witness sets   
     o = fillInDefaultOptions o;
     w1 := {}; w2 := {};
     for x in w#Points do 
	 if residual(matrix {{f}}, matrix x) < o.Tolerance 
	 then w1 = w1 | {x}
	 else w2 = w2 | {x};   
     ( if #w1===0 then null else witnessSet(ideal equations w + ideal f, 
	     -* this is "stretching" the convention that this has to be a complete intersection *-
	     w.Slice, w1), 
       if #w2===0 then null else witnessSet(w.Equations, w.Slice, w2) 
       )
   )

hypersurfaceSection = method(Options =>{Software=>null, Output=>Singular})
hypersurfaceSection(NumericalVariety,RingElement) := o -> (c1,f) -> (
    if DBG>1 then << "-- hypersurfaceSection: "<< endl << 
    "NumericalVariety: " << c1 << endl <<
    "hypersurface: " << f << endl;
    d := sum degree f;
    R := ring f;
    if getDefault Normalize then f = f/sqrt(numgens R * BombieriWeylNormSquared f); 
    c2 := new MutableHashTable; -- new components
    for comp in components c1 do (
	if DBG>2 then << "*** processing component " << peek comp << endl;
	(cIn,cOut) := splitWitness(comp,f); 
	if cIn =!= null then (
	    if DBG>2 then << "( regeneration: " << net cIn << " is contained in V(f) for" << endl <<  
	    << "  f = " << f << " )" << endl;
	    scan(
		partitionViaDeflationSequence( cIn.Points, 
		    polySystem(equations polySystem cIn | slice cIn) 
		    -- this is overdetermined!
		    ),
		pts -> (
		    oldW := witnessSet(cIn.Equations, cIn.Slice, pts);
		    if DBG>2 then << "   old component " << peek oldW << endl;
		    check oldW;    
		    insertComponent(oldW,c2);
		    )
		);
--	    insertComponent(cIn,c2)
	    ); 
	if cOut =!= null 
	and dim cOut > 0 -- 0-dimensional components outside V(f) discarded
	then (
	    s := cOut#Slice;
	    -- RM := (randomUnitaryMatrix numcols s)^(toList(0..d-2)); -- pick d-1 random orthogonal row-vectors (this is wrong!!! is there a good way to pick d-1 random hyperplanes???)
	    RM := random(CC^(d-1),CC^(numcols s));
	    dWS := {cOut} | apply(d-1, i->(
		    newSlice := RM^{i} || submatrix'(s,{0},{}); -- replace the first row
		    moveSlice(cOut,newSlice,Software=>o.Software)
		    ));
	    slice' := submatrix'(comp#Slice,{0},{});
	    local'regular'seq := equations polySystem comp;
	    

	    S := polySystem( local'regular'seq
		| { product flatten apply( dWS, w->sliceEquations(w.Slice^{0},R) ) } -- product of linear factors
		| sliceEquations(slice',R) );
	    T := polySystem( local'regular'seq
		| {f}
		| sliceEquations(slice',R) );
	    
	    -- deflate if singular
	    P := first comp.Points;
	    if status P =!= Singular then targetPoints := track(S,T,flatten apply(dWS,points), 
		NumericalAlgebraicGeometry$gamma=>exp(random(0.,2*pi)*ii),
		Software=>o.Software)
    	    else (
	 	seq := P.DeflationSequenceMatrices;
	 	S' := squareUp(deflate(S, seq), squareUpMatrix P.cache.LiftedSystem); -- square-up using the same matrix
		T' := squareUp(deflate(T, seq), squareUpMatrix P.cache.LiftedSystem); -- square-up using the same matrix
		S'sols := flatten apply(dWS,W->apply(W.Points,p->p.cache.LiftedPoint));
		
	     	T'.PolyMap = (map(ring S', ring T', vars ring S')) T'.PolyMap; -- hack!!!: rewrite with trackHomotopy
	     	lifted'w' := track(S',T',S'sols, 
		    NumericalAlgebraicGeometry$gamma=>exp(random(0.,2*pi)*ii), Software=>o.Software);
	     	targetPoints = apply(lifted'w', p->(
		     	q := project(p,T.NumberOfVariables);
		     	q.cache.SolutionSystem = T;
		     	q.cache.LiftedSystem = T';
		     	q.cache.LiftedPoint = p;
		     	q.cache.SolutionStatus = Singular;
		     	q
		     	));
	 	);
	    LARGE := 100; ---!!!
	    refinedPoints := refine(T, targetPoints, 
		ErrorTolerance=>DEFAULT.ErrorTolerance*LARGE,
		ResidualTolerance=>DEFAULT.ResidualTolerance*LARGE,
		Software=>o.Software);
	    regPoints := select(refinedPoints, p->p.cache.SolutionStatus===Regular);
	    singPoints := select(refinedPoints, p->p.cache.SolutionStatus===Singular);
	    targetPoints = if o.Output == Regular then regPoints else regPoints | solutionsWithMultiplicity singPoints;
	    if DBG>2 then << "( regeneration: " << net cOut << " meets V(f) at " 
	    << #targetPoints << " points for" << endl 
	    << "  f = " << f << " )" << endl;
	    f' := ideal (equations comp | {f});
	    nonJunkPoints := select(targetPoints, p-> not isPointOnAnyComponent(p,c2)); -- this is very slow		    
	    scan(partitionViaDeflationSequence(nonJunkPoints,T),
		pts -> (
		    newW := witnessSet(f',slice',selectUnique(pts, Tolerance=>1e-4));--!!!
		    if DBG>2 then << "   new component " << peek newW << endl;
		    check newW;    
		    insertComponent(newW,c2);
		    )
		)
	    ) 
	);
    	numericalVariety flatten apply(keys c2, i->apply(keys c2#i, j->c2#i#j))
    )


numericalIntersection = method()
numericalIntersection (NumericalVariety, Ideal) := (V,I) -> (
    W := new NumericalVariety from V;
    for f in I_* do W = hypersurfaceSection(W,f);
    W
    )
numericalIntersection (WitnessSet,WitnessSet) := (W1,W2) -> (
    R := ring W1;
    if R =!= ring W2
    then error "expected witness sets in the same ambient space";
    y := symbol y;
    n := numgens R;
    S := (coefficientRing R) monoid([gens R, y_1..y_n]);
    x := take(gens S,n);
    y = take(gens S,-n);
    toSx := map(S,R,x);
    toSy := map(S,R,y);
    W12 := witnessSet(toSx ideal equations W1 + toSy ideal equations W2, 
	toSx ideal slice W1 + toSy ideal slice W2,
	flatten apply(W1.Points, P1->apply(W2.Points, P2-> 
		point {coordinates P1 | coordinates P2}
		))
	);
    numericalIntersection(
	numericalVariety {moveSlice(W12,randomSlice(dim W12, numgens ring W12, coefficientRing ring W12))}, 
	ideal apply(n, i->x#i-y#i)
	)
    )
numericalIntersection (NumericalVariety,NumericalVariety) := (V1,V2) -> (
    V := numericalVariety {};
    for W1 in components V1 do
    for W2 in components V2 do V = V | numericalIntersection(W1,W2);
    V 
    )
TEST ///
CC[x,y,z]; 
W1 = witnessSet (ideal (x^2+y), 2)
W2 = witnessSet (ideal (x^2+y^2-1), 2)
V = numericalIntersection(W1,W2)
assert(dim V == 1 and degree V == 4)
///