/**
 * Returns a random subsample of X of size n which has minimum (amongst 
 * a set of NSAMPLES similar subsamples) maximum distance between points.
 */     
ivec MaxMinDesign::subsample(mat X, int n)
{
    if (n <= 0)
        cerr << "Invalid sample size in MaxMinDesign::subsample(...)" << endl;
    
    double maxMinDist = 0.0;
    ivec bestSubsample = randperm(X.rows());
    
    for (int i=0; i<nsamples; i++) {
        
    	// Generate random subsample
    	ivec irand = randperm(X.rows());
    	ivec irandn = irand(0,n-1);
        mat S = X.get_rows(irandn);
        
        // Compute max distance in this subsample
        double minDist =  distanceMin(S);

        // Keep subsample if has min max distance
        if (minDist > maxMinDist) {
        	bestSubsample = irandn;
        	maxMinDist = minDist;
        	cout << "New min distance: " << maxMinDist << endl;
        }
    }
    
    return bestSubsample;
}
ivec GreedyMaxMinDesign::subsample(mat X, int n)
{
    if (n <= 0)
        cerr << "Invalid sample size in GreedyMaxMinDesign::subsample(...)" << endl;
    
    int imax;
    
    ivec isample(n);        // Indices of points in sample
    ivec iremain;           // Indices of remaining points
    vec D;                  // Vector of min distances to sample
    
    iremain = to_ivec(linspace(0,X.rows()-1,X.rows()));
    
    // Start with location of maximum Z
    max(X.get_col(X.cols()-1), imax);
    isample(0) = imax;
    iremain.del(imax);

    // Add points having maximum minimum distance to sample
    // until subsample size is reached 
    for (int i=1; i<n; i++) 
    {
    	vec xnew = X.get_row(isample(i-1));                // Last point added 
        vec Dnew = dist(X.get_rows(iremain), xnew);        // Distances to xnew
                
        // Update minimum distances to sample
        if (D.length() == 0) 
            D = Dnew;
        else
            D = min(D,Dnew);
        
        // Find point with max min distance
        max(D,imax);
        
        // Add it to sample 
    	isample(i) = iremain(imax);
    	
    	// And delete it from remainder 
    	iremain.del(imax);
    	D.del(imax);
    }
    
    return isample;
}