%Generates simple, bipartite, 3-regular graphs uniformly at random, calculates second largest
%eigenvalue, and stores the eigenvalue if it not 3 (which would signify a graph that is not connected.  
%This is done in a loop running over graph sizes (nVec)
clear all; close all; pack; tic;
options.disp=0;%This makes the 'eigs' function not display the iterations converging to the eigenvalue
SampleSize = 1000;%number of steps per walks
k=3;%degree of regularity of the graphs
nVec=[1258 1584 1995 2511 3162 3981 5011 6309 7943 10000];%n is size of HALF of the (bipartite) graph.
EigenTwo=0;
EigenTwo=zeros(SampleSize, length(nVec));
for c=1:length(nVec)
%This loop runs over graphs sizes   
   n=nVec(c);
   for w = 1:SampleSize
   %This loop runs over how many eigenvalues should be generated for each graph size   
      A=spalloc(n,n,3*n); 
      while(max(max(A))~=1)%Continues until SIMPLE graphs is found
         %This loop uses Bollobas' configuration model algorithm to generate
         %k-regular graphs.  
         %For a good description see section 2 in N.C. Wormald's Models of Random Regular Graphs
         Pairs=mod([randperm(n*k); randperm(n*k)+n],n);
         A=spalloc(2*n,2*n,3*n);  
         for i=1:(n*k)
         %This loop fills in the adjacency matrix   
            m1= Pairs(1,i)+1;
            m2= Pairs(2,i)+n+1;         
            A(m1,m2) =  A(m1,m2) + 1;
            A(m2,m1) =  A(m2,m1) + 1;
         end
      end
      E=sort(eigs(A,2,'LA', options));%2 sorted Eigenvalues of A.
      if((E(1)==E(2))==0)%True if A represents a CONNECTED graph
         EigenTwo(w,c)=E(1);
      else
         w=w-1;
         %Theoretically, this line makes an infinite loop possible. However, this wasn't a problem.
      end
   end
   save Mother3 EigenTwo SampleSize nVec %Saves data after each graph size
end
RunTime=toc;
save Mother3 EigenTwo n RunTime nVec