private double[] makeNewParamVariations(double[][] simp, int bestVertexNumber,
            double[] initialParams, double[] initialParamVariations) {
        double[] paramVariations = new double[numParams];   // will be the return value
        double[] relatedTo = new double[numParams];         // parameter variation should be related to (in size) these values
        double logTypicalRelativeVariation = 0;
        for (int i=0; i<numParams; i++) {                   // for all parameters
            double variation = 0;                           // roughly size of simplex in direction of that parameter
            for (int v=0; v<numVertices; v++)
                if (v != bestVertexNumber) {
                    double delta = Math.abs(simp[v][i] - simp[bestVertexNumber][i]);
                    paramVariations[i] += delta*delta;
                }
            paramVariations[i] = 10*Math.sqrt(paramVariations[i]); // make the new simplex larger than the old one
            relatedTo[i] = initialParamVariations!=null && initialParamVariations.length>= numParams ?
                    initialParamVariations[i] :             // relate to initialParamVariations (if given),
                    Math.max(Math.abs(initialParams[i]), Math.abs(simp[bestVertexNumber][i]));
            double logRelativeVariation = paramVariations[i]>relatedTo[i] ? 0 :
                    Math.log(paramVariations[i]/relatedTo[i]);
            logTypicalRelativeVariation += logRelativeVariation;
        }
        logTypicalRelativeVariation /= numParams;
        double typicalRelativeVariation = Math.exp(logTypicalRelativeVariation);
        final double WORST_RATIO = 1e-3;        //parameter variation should not be lower than typical value by more than this
        for (int i=0; i<numParams; i++)
            if (paramVariations[i]<relatedTo[i] && paramVariations[i]/relatedTo[i] < typicalRelativeVariation*WORST_RATIO)
                paramVariations[i] = relatedTo[i]*typicalRelativeVariation*WORST_RATIO;
        return paramVariations;
    }