%
%    This file computes Heegaard Floer homology starting form the data in data.m
%    It also needs the files setprod.m, loop.m and maslov.m
%
%    Ciprian Manolescu - May 18, 2005
%
%

[Alpha, Gamma, Beta] = data;

% computes genus
g = length (Alpha);
if (length(Gamma) ~= g) 
	error ('Alpha and Gamma should have the same length.')
end

% computes number of vertices on each beta curve
for i=1:g
	N(i) = length(Beta(i).curve);
end

% changes Beta.point to the absolute values
% makes a new entry Beta.sign with the signs

for i=1:g
	Beta(i).sign = sign (Beta(i).point);
	Beta(i).point = abs (Beta(i).point);
	if any(Beta(i).point == 1)
		error ('The first point on an alpha curve should be on a gamma curve.')
	end
end

% forms a matrix V with the intersections of alpha and beta curves
% first column tells you which alpha curve, second which point on that 
% alpha curve, third which beta curve, fourth which point on the beta
% fifth column is made of 1's - code for an alpha-beta intersection 
% later we'll add beta-gamma and alpha-gamma intersections 

% also writes alpha and beta curves in terms of vertices
% the results are cell arrays Av and Bv
% so far they show 0 when there is an intersection with gamma
% we also make a cell array Aw by eliminating the zeros in Av i.e.
% Aw encodes only the intersections with the beta curves

V = [];
Av = [];
Bv = [];
Aw = [];
Cv = [];

k=1;
for i=1:g
	jj=1;
	for j=2:Alpha(i)
		V(k,1)=i;
		V(k, 2)=j;
		for l=1:g
			for s=1:N(l)
			 if ((Beta(l).curve(s)==i) & (Beta(l).point(s)==j)) 
					V(k, 3)=l;
					V(k, 4)=s;
					V(k, 5)=1;
					Bv{l}(s)=k;
					Av{i}(j)=k; 
					Aw{i}(jj)=k;
					jj = jj+1;
					continue
			  end 
			end
		end 	
		k=k+1;
	end
end


% generates all possible permutations of the beta curves
PBv = perms (Bv);

% finds all generators

G = [];
UV = [];
for i = 1:factorial(g)
	for j = 1:g
        	UV{j} = intersect (Aw{j}, PBv{i,j});
	end
	G=[G; setprod(UV)];
end

% number of generators for the Heegaard Floer complex
[numg, whocares] = size(G);

% now we're adding intersections of alpha and gamma curves to our V
% first column tells you which alpha curve, second which point on that
% alpha curve, third which gamma curve, fourth which point on the gamma.
% fifth column is made of 2's - code for an alpha-gamma intersection

% we also fill in Av, and form a new cell array Cv with the gamma curves

for i=1:g
	V(k, 1)=i;
	V(k, 2)=i;
	V(k, 3)=i;
	V(k, 4)=i;
	V(k, 5)=2;
	Av{i}(1)=k;
	Cv{i}(1)=k;
	k=k+1;
end 

% now we're adding intersections of beta and gamma curves to our V
% first column tells you which beta curve, second which point on that
% beta curve, third which gamma curve, fourth which point on the gamma.
% fifth column is made of 3's - code for an beta-gamma intersection
                                                                                
% we also fill in Bv and Cv

for i=1:g
        for j=2:Gamma(i)
                V(k,3)=i;
                V(k,4)=j;
                for l=1:g
                        for s=1:N(l)
                         if ((Beta(l).curve(s)==-i) & (Beta(l).point(s)==j))
                                        V(k, 1)=l;
                                        V(k, 2)=s;
                                        V(k, 5)=3;
                                        Bv{l}(s)=k;
                                        Cv{i}(j)=k;
                                        continue
                          end
                        end
                end
                k=k+1;
        end
end


% number of 0-cells (vertices) in our complex
[numv, whocares] = size(V);

disp(' ')
disp(['This diagram has ' num2str(numv) ' vertices.'])
answer = input ('Do you want to see them? (y/n) ', 's');
if (answer=='y')
	disp (' ')
	disp ('Each vertex can be identified with a point on exactly two curves.')
	disp ('For example, a2(5) b3(7) means that the vertex is the fifth point on the second') 
	disp ('alpha curve and the seventh point on the third beta curve.')
	disp ('Press any key to continue.')
	disp (' ')
	pause
        for i=1:numv
		if V(i, 5) == 1
			disp ([num2str(i), '  a', num2str(V(i,1)),'(', num2str(V(i,2)), ') b', num2str(V(i,3)), '(', num2str(V(i,4)), ')'])		
		elseif V(i,5) == 2
			disp ([num2str(i), '  a', num2str(V(i,1)),'(', num2str(V(i,2)), ') c', num2str(V(i,3)), '(', num2str(V(i,4)), ')'])
		else
			disp ([num2str(i), '  b', num2str(V(i,1)),'(', num2str(V(i,2)), ') c', num2str(V(i,3)), '(', num2str(V(i,4)), ')'])
		end
	end
	disp (' ')
end

answer='y';
while (answer=='y')
	answer = input ('Do you want to see a curve? (y/n) ', 's');
	if (answer ~= 'y') break, end
	type=input ('Type of curve (a/b/c) : ', 's');
	numc = input (['Number of curve (an integer between 1 and ' num2str(g) '): ']); 
	disp ('Here are the vertices on the curve, in order:')
	if (type=='a')
		disp (Av{numc})
	elseif (type=='b')
		disp (Bv{numc})
	elseif (type=='c')
		disp (Cv{numc})
	end				
end


% reorder the g elements inside each generator, so that the first is a
% point on the first beta curve, the second on the second, etc.
% the result is the matrix Gbeta

Gbeta = [];
                                                                                         
for i=1:numg
        for j =1:g
                whichbeta = V(G(i, j), 3);
                Gbeta(i, whichbeta) = G (i, j);
        end
end
                                                                                         
% the number of generators on each beta curve
                                                                                         
for i = 1:g
        Sizeofbeta(i)=length(Beta(i).curve);
end

% encode all edges into a matrix with three columns
% the first shows the type of curve on which it lies:
% 1 for alpha, 2 for beta, 3 for gamma
% the second shows the number of the respective a/b/c curve
% the third shows the number of its starting point on the curve

% EE is a cell array saying which edges appear on each a/b/c curve

EE = [];
Edge = [];

j=1;
for i = 1:g
	for k =1:(Alpha(i))
		Edge (j, 1) = 1;
		Edge (j, 2) = i;
		Edge (j, 3) = k;
		EE {1, i} (k) = j;
		j = j +1;
	end
end

for i = 1:g
        for k =1:(Sizeofbeta(i))
                Edge (j, 1) = 2;
                Edge (j, 2) = i;
                Edge (j, 3) = k;
		EE {2, i} (k) = j;
                j = j +1;
        end
end

for i = 1:g
        for k =1:(Gamma(i))
                Edge (j, 1) = 3;
                Edge (j, 2) = i;
                Edge (j, 3) = k;
		EE {3, i} (k) = j;
                j = j +1;
        end
end

% number of 1-cells (edges) in our complex
[nume, whocares] = size(Edge);


% find the domains (2-cells) in the diagram
% we encode them in a cell array Dom that indicates
% the edges on the boundary, counterclockwise 
% a minus sign means the orientation on the edge is the opposite one

% we run through all the edges as long as it's necessary
% in the process we form a matrix ED (edges in terms of domains)
% the first column tells the domain on its left
% the second the domain on its right
% the third is 0 at the beginning, 2 at the end (the number of times
% it has appeared as part of a domain)

Dom = [];
ED = zeros (nume, 3);
j = 0;



for i = 1:nume
for u = 1:2
if ((ED (i, u))  == 0)
	ED (i, 3) = ED (i, 3) + 1;
	% construct a new domain to the left or to the right, according to whether u = 1 or 2
	j = j+1;
	if u==1
		edg = i;
		ED (i, 1) = j;
	else
		edg = -i;
		ED (i, 2) = j;
	end
	k=1;
	Dom{j}(1) = edg;
	aedg = abs (edg);
	semn = sign (edg);
	while 1
		if ((Edge(aedg, 1)) == 1) & (semn == 1)
			% what to do for an alpha curve in the right direction !!!!!!!!!!!!!!
			e = Edge (aedg, 2);
			if (Edge(aedg,3) == (Alpha(e)))
				% go up on the gamma curve
				edg = EE {3, e} (1);	
				ED (edg, 1) = j;			
			else
				% go up on the beta curve
				vertex = Av{e}(Edge(aedg,3) +1);
				whichbeta = V (vertex, 3);
				whichpoint = V (vertex, 4);
				if (Beta(whichbeta).sign(whichpoint)) == 1
					edg = EE {2, whichbeta} (whichpoint);	
					ED (edg, 1) = j;
				else				
					if (whichpoint == 1)
						edg = -EE {2, whichbeta} (Sizeofbeta(whichbeta));	
					else
						edg = -EE {2, whichbeta} (whichpoint -1);
					end
					ED (-edg, 2) = j;
				end
			end
		elseif ((Edge(aedg, 1)) == 1) & (semn == -1)
			% what to do for an alpha curve in the wrong direction !!!!!!!!!!!!!!!
                        e = Edge (aedg, 2);
                        if (Edge(aedg,3) == 1)
                                % go down on the gamma curve
                                edg = -EE {3, e} (Gamma(e));
                                ED (-edg, 2) = j;
                        else
                                % go down on the beta curve
                                vertex = Av{e}(Edge(aedg,3));
                                whichbeta = V (vertex, 3);
                                whichpoint = V (vertex, 4);
                                if (Beta(whichbeta).sign(whichpoint)) == (-1)
                                        edg = EE {2, whichbeta} (whichpoint);
                                        ED (edg, 1) = j;
                                else
                                        if (whichpoint == 1)
                                                edg = -EE {2, whichbeta} (Sizeofbeta(whichbeta));
                                        else
                                                edg = -EE {2, whichbeta} (whichpoint -1);
                                        end
                                        ED (-edg, 2) = j;
                                end
			end

		elseif ((Edge(aedg, 1)) == 2) & (semn == 1)
			% what to do for a beta curve in the right direction !!!!!!!!!!!!!!!!!
			e = Edge (aedg, 2);
			vertex = Edge (aedg, 3);
			if vertex == (Sizeofbeta(e))			
				vertex = 1;
			else 
				vertex = vertex + 1;
			end
			
			whichcurve = Beta(e).curve(vertex);
			if (sign (whichcurve)) == 1
				% we continue on an alpha curve
				whichpoint = Beta(e).point(vertex);
				if (Beta(e).sign(vertex)) == 1
					% we go left on the alpha curve
					vertex = Bv{e}(vertex);
					vertex = V(vertex, 2) - 1;
					if (vertex == 0) 
						vertex = Alpha(whichcurve);
					end
					edg = -EE {1, whichcurve} (vertex);
					ED (-edg, 2) = j;
				else
					% we go right on the alpha curve
					vertex = Bv{e}(vertex);
					vertex = V (vertex, 2);
					edg = EE {1, whichcurve} (vertex);
					ED (edg, 1) = j;
				end

			else
				% we continue on a gamma curve
				whichcurve = - whichcurve;
				whichpoint = Beta(e).point(vertex);
                                if (Beta(e).sign(vertex)) == -1
                                        % we go clockwise on the gamma curve
                                        vertex = Bv{e}(vertex);
                                        vertex = V(vertex, 4) - 1;
                                        if (vertex == 0)
                                                vertex = Gamma(whichcurve);
                                        end
                                        edg = -EE {3, whichcurve} (vertex);
                                        ED (-edg, 2) = j;
                                else
                                        % we go counterclockwise on the gamma curve
                                        vertex = Bv{e}(vertex);
                                        vertex = V (vertex, 4);
                                        edg = EE {3, whichcurve} (vertex);
                                        ED (edg, 1) = j;
                                end				
			end


		elseif ((Edge(aedg, 1)) == 2) & (semn == -1)
			% what to do for a beta curve in the wrong direction !!!!!!!!!!!!!!!!!!!
			e = Edge (aedg, 2);
                        vertex = Edge (aedg, 3);

                        whichcurve = Beta(e).curve(vertex);
			if (sign (whichcurve)) == 1
                                % we continue on an alpha curve
                                whichpoint = Beta(e).point(vertex);
                                if (Beta(e).sign(vertex)) == -1
                                        % we go left on the alpha curve
                                        vertex = Bv{e}(vertex);
                                        vertex = V(vertex, 2) - 1;
                                        if (vertex == 0)
                                                vertex = Alpha(whichcurve);
                                        end
                                        edg = -EE {1, whichcurve} (vertex);
                                        ED (-edg, 2) = j;
                                else
                                        % we go right on the alpha curve
                                        vertex = Bv{e}(vertex);
                                        vertex = V (vertex, 2);
                                        edg = EE {1, whichcurve} (vertex);
                                        ED (edg, 1) = j;
                                end

                        else
                                % we continue on a gamma curve
                                whichcurve = - whichcurve;
                                whichpoint = Beta(e).point(vertex);
                                if (Beta(e).sign(vertex)) == 1
                                        % we go clockwise on the gamma curve
                                        vertex = Bv{e}(vertex);
                                        vertex = V(vertex, 4) - 1;
                                        if (vertex == 0)
                                                vertex = Gamma(whichcurve);
                                        end
                                        edg = -EE {3, whichcurve} (vertex);
                                        ED (-edg, 2) = j;
                                else
                                        % we go counterclockwise on the gamma curve
                                        vertex = Bv{e}(vertex);
                                        vertex = V (vertex, 4);
                                        edg = EE {3, whichcurve} (vertex);
                                        ED (edg, 1) = j;
                                end
                        end


		elseif ((Edge(aedg, 1)) == 3) & (semn == 1)
			 % what to do for a gamma curve in the right direction !!!!!!!!!!!!!!!!!
			e = Edge (aedg, 2);
			if (Edge(aedg,3) == (Gamma(e)))
                                % go left on the alpha curve
                                edg = -EE {1, e} (Alpha(e));
                                ED (-edg, 2) = j;
                        else
                                % go inward on the beta curve
                                vertex = Cv{e}(Edge(aedg,3) +1);
                                whichbeta = V (vertex, 1);
                                whichpoint = V (vertex, 2);
                                if (Beta(whichbeta).sign(whichpoint)) == (-1)
                                        edg = EE {2, whichbeta} (whichpoint);
                                        ED (edg, 1) = j;
                                else
                                        if (whichpoint == 1)
                                                edg = -EE {2, whichbeta} (Sizeofbeta(whichbeta));
                                        else
                                                edg = -EE {2, whichbeta} (whichpoint -1);
                                        end
                                        ED (-edg, 2) = j;
                                end
                        end



		elseif ((Edge(aedg, 1)) == 3) & (semn == -1)
			 % what to do for a gamma curve in the wrong direction !!!!!!!!!!!!!!!!!!!
			e = Edge (aedg, 2);
                        if (Edge(aedg,3) == 1)
                                % go right on the alpha curve
                                edg = EE{1, e}(1);
                                ED (edg, 1) = j;
                        else
                                % go down on the beta curve
                                vertex = Cv{e}(Edge(aedg,3));
                                whichbeta = V (vertex, 1);
                                whichpoint = V (vertex, 2);
                                if (Beta(whichbeta).sign(whichpoint)) == 1
                                        edg = EE {2, whichbeta} (whichpoint);
                                        ED (edg, 1) = j;
                                else
                                        if (whichpoint == 1)
                                                edg = -EE {2, whichbeta} (Sizeofbeta(whichbeta));
                                        else
                                                edg = -EE {2, whichbeta} (whichpoint -1);
                                        end
                                        ED (-edg, 2) = j;
                                end
                        end


		end

		aedg = abs (edg);
		semn = sign (edg);
		if (edg == (Dom{j}(1))), break, end
		ED (aedg, 3) = ED (aedg, 3) + 1;
		k = k+1;
		Dom{j}(k) = edg;
	end		
end
end
end

% number of domains
numd = j;

disp (' ')
disp(['This diagram has ' num2str(numd) ' two-cells.'])


% display the domains in terms of vertices
% encode them into a cell array Dov similar to Dom
% Typedom tells the number of vertices for each domian

Dov = [];
Typedom = [];
for i=1:numd
	Typedom(i) = length(Dom{i});
	for j=1:Typedom(i)
		edg = Dom{i}(j);
		aedg = abs(edg);
		semn = sign(edg);		
		if semn == 1
			if (Edge(aedg,1) == 1)
				% on an alpha curve			
				Dov{i}(j) = Av{Edge(aedg,2)}(Edge(aedg,3));
			elseif (Edge(aedg,1) == 2)			
				% on a beta curve
				Dov{i}(j) = Bv{Edge(aedg,2)}(Edge(aedg,3));
			else
				% on a gamma curve
				Dov{i}(j) = Cv{Edge(aedg,2)}(Edge(aedg,3));
			end
		else
			if (Edge(aedg,1) == 1)
                                % on an alpha curve
				if (Edge(aedg,3) == Alpha(Edge(aedg,2))) 
					vertex = 1;
				else
					vertex = Edge(aedg,3) + 1;
				end				
                                Dov{i}(j) = Av{Edge(aedg,2)}(vertex);
                        elseif (Edge(aedg,1) == 2)
                                % on a beta curve
				if (Edge(aedg,3) == Sizeofbeta(Edge(aedg,2)))
                                        vertex = 1;
                                else
                                        vertex = Edge(aedg,3) + 1;
                                end
                                Dov{i}(j) = Bv{Edge(aedg,2)}(vertex);
                        else
                                % on a gamma curve
				if (Edge(aedg,3) == Gamma(Edge(aedg,2)))
                                        vertex = 1;
                                else
                                        vertex = Edge(aedg,3) + 1;
				end
                                Dov{i}(j) = Cv{Edge(aedg,2)}(vertex);
			end
		end
	end	
end



answer = input ('Do you want to see them? (y/n) ', 's');
if (answer=='y')
	disp (' ')
	disp ('Each two-cell is shown in terms of its vertices:')
	disp (' ')
        for i=1:numd
		disp (['Cell ' num2str(i) ' : '])
		disp (Dov{i})
	end
end



% set the basepoint
basept = input ('In which cell do you want to put the basepoint? ');

% the matrices BA and BG contain the intersection numbers
% between beta(i) and alpha(j), and beta(i) and gamma(j), respectively

BA = zeros (g, g);
BG = zeros (g, g);
for i=1:g
        for j=1:Sizeofbeta(i)
                if (Beta(i).curve(j)) > 0
                         ind = Beta(i).curve(j);
                         BA(i, ind) = BA(i, ind) + Beta(i).sign(j);
                else
                        ind = -Beta(i).curve(j);
                        BG(i, ind) = BG(i, ind) + Beta(i).sign(j);
                end
        end
end




if (det(BA) == 0)
        error ('This is not a rational homology sphere.')
end


% we decompose the generators in G into spin^c structures
% the vector Spstr has Spstr(i) = the spinc structure of G(i)

Spstr = zeros (numg, 1);
index = 1;
spc = 1;
jj=1;

while 1
        Spstr (index) = jj;
        for ii = index : numg
                if ((Spstr(ii)) == 0)
                        pone = index;
                        ptwo = ii;
                        loop;
                        if (spinc == 1)
                                Spstr (ii) = jj;
                        end
                end
        end
        ii = index;
        while ii < (numg+1)
                if ((Spstr(ii)) == 0), break, end
                ii=ii+1;
        end
        if (ii == (numg + 1)) break, end
        index = ii;
        jj = jj+1;
end

% number of spin^c structures
nums = jj;

% count the elements in each spin^c structure

Spincount = zeros (nums, 1);
for i = 1:numg
        j = Spstr (i);
        Spincount (j) = Spincount (j) + 1;
end
Spincount = Spincount' ;


disp (' ')
disp (['This diagram has ' num2str(nums) ' spinc structures.'])
disp ('Number of elements in each spinc structure: ')
disp (Spincount)


% make a matrix NewG by adding a first column with numbers 1:numg, and one with
% the corresponding spin^c structures

New = [1:numg]';
NewG = [New, G, Spstr];

disp(['This diagram has ' num2str(numg) ' generators.'])
answer = input ('Do you want to see them? (y/n) ', 's');
if (answer=='y')
	disp (' ')
	disp (['Each generator consists of ', num2str(g), ' vertices. After an index, we show']) 
	disp ('these vertices and the corresponding spinc structure.') 
	disp ('Press any key to continue.')
	pause
	disp (' ')
        disp (NewG)
end


while 1

whichspin = input ('Which spinc structure are you interested in? ');
disp (' ')
disp ('Here are the generators and their relative Maslov gradings: ')
disp (' ')

% the vector Ourspin contains all the elemnts in that spinc structure
Ourspin = [];
for i = 1:numg
        if (Spstr(i) == whichspin)
                Ourspin = [Ourspin; i];
        end
end

% compute the Maslov indices with respect to Ourspin(1)
% encode the result in Ourmaslov

Ourmaslov = [];

ss = Spincount(whichspin);
ptwo = Ourspin (1);
for ii = 1:ss
        pone = Ourspin(ii);
	power = 0;
        maslov;
        Ourmaslov (ii) = round(masl);
end

minm = min(Ourmaslov);
maxm = max(Ourmaslov);
diff = maxm - minm + 1;

% put the elements in order of their gradings
% encode the result into a cell array Result

for i=1:diff
        Result{i} = [];
end
for i = 1:ss
        j = Ourmaslov (i) - minm + 1;
        Result{j} = [Result{j}, Ourspin(i)];
end

% display the result
for i=1:diff
        disp (['Grading ', num2str(diff -i), ':  ', num2str(Result{diff + 1 - i}) ])
end


% guess the differentials

disp (' ')
disp ('For each domain of index 1, a potential holomorphic disk in the symmetric')
disp ('product has a preimage in Sym^{g-1}(\Sigma) \times Sigma which consists of t')
disp ('trivial disks and a connected surface of genus g with b boundary components.')
disp (' ')
disp ('There are positive domains of index 1 between the following pairs: ')
disp (' ')

% look at domains with power of U = 0 first
for ii=1:(diff-1)
	for jj = 1:length(Result{diff + 1 - ii})
		pone = Result{diff + 1 - ii}(jj);
		for kk = 1:length(Result{diff - ii})
			ptwo = Result{diff - ii}(kk);
			power = 0;		
			maslov;
			if all(MD > (-1))
				disp ([ '(', num2str(pone), ',' ,num2str(ptwo), ') t=', num2str(triv), ' g=', num2str(genus), ' b=', num2str(cycles)])
			end 			
		end
	end
end

% look at domains with positive powers of U
for hh = 1:(ceil((diff-1)/2))
	for ii=(diff+1-(2*hh)):-1:1
        for jj = 1:length(Result{ii})
                pone = Result{ii}(jj);
                for kk = 1:length(Result{ii - 1 + (2*hh)})
                        ptwo = Result{ii-1+(2*hh)}(kk);
                        power = hh;
                        maslov;
			if (masl ~= 1)
				error ('Something is terribly wrong.');
			end
                        if all(MD > (-1))
                                disp ([ '(', num2str(pone), ',(U^' ,num2str(power), ')', num2str(ptwo), ') t=', num2str(triv), ' g=', num2str(genus), ' b=', num2str(cycles)]);
			end
                end
        end
	end
end





% look more closely at differentials
answer='y';
while (answer=='y')
	disp (' ')
        answer = input ('Do you want to look at a domain? (y/n) ', 's');
        if (answer ~= 'y') break, end
        pone=input ('First generator: ');
	power = input ('Power of U for the second generator: ');
	ptwo = input ('Second generator: ');
	maslov;
	disp (' ')
	disp ('This domain consist of the following two-cells, with the given multiplicities:')
	disp (' ')
	disp(MDred)
end


disp (' ');
answer = input ('Do you want to go to a new spinc structure? (y/n) ', 's');
if (answer ~= 'y') break, end
end
