function B=q(Ne,Nmin,Nmax,alpha,d,c,n)
% A program to solve the Queen Problem
% via the Fully Adaptive Cross-Entropy method
%
% Syntax: B=q(Ne,Nmin,Nmax,alpha,d,c,n)
%
% Inputs -
%   Ne:    Number of elite samples to use
%   Nmin:  Minimum number of samples to use (must be >= Ne)
%   Nmax:  Maximum number of samples to use (must be >= Ne)
%   alpha: Smoothing Parameter
%
% Extra Inputs -
%   d:     number of S_t^*'s same in a row with no gamma_hat_t improvement
%   c:     number of Nt's=Nmax in a row  
%   n:     n queens on an nxn board
%
% Output -
%   B:     An nxn matrix with queen's denoted as 1's, and blank
%          squares denoted as 0's

% some default parameters if they are not supplied
if nargin<7,n=8;end
if nargin<6,c=4;end
if nargin<5,d=6;end
if nargin <4,alpha=0.7;end
if nargin ==0,Ne = 20;end
if nargin <2,Nmin = 10*Ne;Nmax = 500*Ne;end
if (Nmin<Ne)||(Nmax<Ne)||(Nmax<Nmin),
    fprintf('Please give a valid (Ne,Nmin,Nmax) tuple.\n')
    B=0;return;
end
N=Nmin; % start sampling with the minimum allowed
st=rand(d,1)+n*n;
nt=rand(c,1);
gt=100;
v=(1/n)*ones(n); % initial probabilities
iii=1;
ind=1;
count=1;
ccc=0;
while iii~=0,
    if (N+ccc)>=Nmax,
        if (sum(nt>=Nmax)==c), % we have reached the limit here
            fprintf('unreliable solution!\n')
            break;
        end
    end
    s=[]; % set up score vector
    for kk=1:N, % calculate and score N_t queen layouts
        B=genq(v,n);
        S=scoreq(B,n);    
        s=[s;S];
        V(:,:,kk)=B;
    end
    [s,I]=sort(s); % Sort the scores
    gtold=gt;
    gt=s(Ne);
    V=V(:,:,I(1:Ne)); % the elite samples
    if s(1)==0, % if we have a valid solution
        fprintf('t = %d , N_t = %d , g_hat_t = %g , S_star_t = %d\n',count,N,s(Ne),s(1))
        fprintf('valid solution!\n')
        break;
    end
    if s(Ne)<gtold,
        st=rand(d,1)+n*n; % reset counting for s_star_t
    end
    if (gt>=gtold)&&(s(1)>=st(d)),
        if (sum(st==s(1))==d),
            fprintf('reliable solution.\n')
            break;
        else
            ccc=0;
            s=s(1:Ne);
            fprintf('N_t: %d ',Nmin)
            while ind~=0,
                if Nmin==Nmax,break;end
                B=genq(v,n);
                S=scoreq(B,n);    
                ccc=ccc+1;
                if S<s(Ne),
                    s=[s;S];
                    V(:,:,Ne+1)=B;
                    [s,I]=sort(s);
                    s=s(1:Ne);
                    V=V(:,:,I(1:Ne));
                    if (s(1)==0),
                        fprintf('\nt = %d , N_t = %d , g_hat_t = %g , S_star_t = %d\n',count,N+ccc,s(Ne),s(1))
                        fprintf('valid solution!\n')
                        B=V(:,:,1);
                        return;
                    end
                end
                if mod(ccc,5*Nmin)==0,
                    fprintf('\nN_t:')
                end
                if mod(ccc,Nmin)==0,
                    fprintf(' %d ',N+ccc)
                elseif mod(ccc,round(Nmin/5))==0,
                    fprintf('.')
                end
                if s(Ne)<gtold,
                    st=rand(d,1)+n*n; % reset counting for s_star_t
                    break;
                end
                if ((N+ccc)>=Nmax)||(s(1)<st(d)),
                    break;
                end
            end
            gt=s(Ne);
            w=(1/Ne)*sum(V,3);
            v=alpha*w+(1-alpha)*v;
            fprintf('\nt = %d , N_t = %d , g_hat_t = %g , S_star_t = %d\n',count,N+ccc,s(Ne),s(1))
            N=Nmin;
            count = count+1;
            st(1:(d-1))=st(2:d);
            st(d)=s(1);
            nt(1:(c-1))=nt(2:c);
            nt(c)=N+ccc;
        end
    else
        if gt<gtold,
            nt=rand(c,1);
        end
        w=(1/Ne)*sum(V,3);
        v=alpha*w+(1-alpha)*v;
        fprintf('t = %d , N_t = %d , g_hat_t = %g , S_star_t = %d\n',count,N,s(Ne),s(1))
        N=Nmin;
        count = count+1;
        st(1:(d-1))=st(2:d);
        st(d)=s(1);
        nt(1:(c-1))=nt(2:c);
        nt(c)=N;
    end
end
B=V(:,:,1);