我遇到排序和IComparer()
的问题。我的程序停在它上面。我是C#的初学者。
以下是代码停止的部分:
public ArrayList ModelSort()
{
IComparer sorter = new R2SortHelper();
InnerList.Sort(sorter);
return InnerList;
}
private class R2SortHelper : System.Collections.IComparer
{
public int Compare(object x, object y)
{
double m1 = ((Model)x).R2() + ((Model)x).Valid().GetHashCode();
double m2 = ((Model)y).R2() + ((Model)y).Valid().GetHashCode();
if (m1 > m2)
return -1;
else if (m1 < m2)
return 1;
else
return 0;
}
}
以下是来自控制台的错误:
Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: 'AMO.EnPI.AddIn.Utilities.ModelCollection+R2SortHelper'.
例外情况:
例外文字
System.ArgumentException:无法排序,因为IComparer.Compare()方法返回不一致的结果。要么值不等于自身,要么重复一个值与另一个值进行比较会产生不同的结果。 IComparer:&#39; AMO.EnPI.AddIn.Utilities.ModelCollection + R2SortHelper&#39;。 在System.Array.SorterObjectArray.DepthLimitedQuickSort(Int32 left,Int32 right,Int32 depthLimit) 在System.Array.SorterObjectArray.DepthLimitedQuickSort(Int32 left,Int32 right,Int32 depthLimit) 在System.Array.Sort(数组键,数组项,Int32索引,Int32长度,IComparer比较器) 在System.Collections.ArrayList.Sort(Int32索引,Int32计数,IComparer比较器) 在System.Collections.ArrayList.Sort(IComparer comparer) 位于C:\ ENPI \ EnPI \ AMO.EnPI-5.0 \ AMO.EnPI.Utilities \ Analytics.cs中的AMO.EnPI.AddIn.Utilities.ModelCollection.ModelSort():第961行 位于C:\ ENPI \ EnPI \ AMO.EnPI-5.0 \ AMO.EnPI.AddIn \ ModelSheet.cs中的AMO.EnPI.AddIn.ModelSheet.WriteResultsTable(Int32 n,Boolean top):第146行 位于C:\ ENPI \ EnPI \ AMO.EnPI-5.0 \ AMO.EnPI.AddIn \ ModelSheet.cs中的AMO.EnPI.AddIn.ModelSheet.Populate():第60行 位于C:\ ENPI \ EnPI \ AMO.EnPI-5.0 \ AMO.EnPI.AddIn \ ThisAddIn.cs中的AMO.EnPI.AddIn.ThisAddIn.plotEnPI(ListObject LO):第318行 at AMO.EnPI.AddIn.RegressionControl.runFunction(Object sender,EventArgs e)位于C:\ ENPI \ EnPI \ AMO.EnPI-5.0 \ AMO.EnPI.AddIn \ RegressionControl.cs:第817行 at AMO.EnPI.AddIn.CO2EmissionControl.btnCalculate_Click(Object sender,EventArgs e)位于C:\ ENPI \ EnPI \ AMO.EnPI-5.0 \ AMO.EnPI.AddIn \ CO2EmissionControl.cs:第148行
我的模特课:
public class Model
{
public int ModelNumber { get; set; }
public double[] Ys { get; set; }
public double[,] Xs { get; set; }
public string[] VariableNames { get; set; }
public double RMSError { get; set; }
public double[] Coefficients { get; set; }
public Model()
{
ModelNumber = 0;
Ys = null;
Xs = null;
VariableNames = null;
RMSError = 0;
Coefficients = null;
}
public Model(int ModelNumber, double[] Ys, double[,] Xs, string[] VariableNames)
{
RMSError = 0;
Coefficients = null;
// run LLS
int info;
double[] c;
alglib.lsfitreport rep;
try
{
alglib.lsfitlinear(Ys, Xsplusone(), out info, out c, out rep);
}
catch
{
throw;
}
Coefficients = c;
RMSError = rep.rmserror;
}
public void Run() //double[] Ys, double[,] Xs, string[] VariableNames)
{
RMSError = 0;
Coefficients = null;
if (Ys != null && Xs != null)
{
// run LLS
int info;
double[] c;
alglib.lsfitreport rep;
try
{
alglib.lsfitlinear(Ys, Xsplusone(), out info, out c, out rep);
}
catch
{
throw;
}
Coefficients = c;
RMSError = rep.rmserror;
}
}
public int N()
{
return Ys.Count();
}
public int df()
{
return N() - k() - 1;
}
public int k()
{
return VariableNames.Count();
}
public double TotalSS()
{
// compute total sum of squares
double ybar = Ys.Average();
double sst = 0;
for (int i = Ys.GetLowerBound(0); i <= Ys.GetUpperBound(0); i++)
{
sst += Math.Pow(Ys[i] - ybar, 2);
}
return sst;
}
public double ResidualSS ()
{
return ( N() * Math.Pow( RMSError, 2));
}
public double R2()
{
return (1 - (ResidualSS() / TotalSS()));
}
public double AdjustedR2()
{
return (1 - (((1 - R2()) * (N() - 1)) / (N() - k() - 1)));
}
public double F()
{
return ( (R2() / k()) / ((1 - R2()) / (N() - k() - 1)));
}
public double ModelPValue()
{
double modelP = 0;
double modelF = F();
if (modelF < 0) modelF = 0;
try
{
modelP = alglib.fcdistribution(N() - df() - 1, df(), modelF);
}
catch (alglib.alglibexception e)
{
}
return modelP;
}
public bool Valid()
{
// Model validity criteria, from the SEP M&V protocol:
// The model p-value must be less than 0.1
// All variables must have p-values less than 0.2
// At least one variable must have a p-value of less than 0.1
// The R2 value must be greater than 0.5
double[] ps = PValues();
bool varsvalid = true;
bool varlowexists = false;
for (int i = 0; i < ps.Count(); i++)
{
if (ps[i] <= Constants.PVALUE_THRESHOLD)
varlowexists = true;
if (ps[i] > Constants.PVALUE_HIGH)
varsvalid = false;
}
if (!varlowexists)
return false;
if (!varsvalid)
return false;
if (ModelPValue() > Constants.PVALUE_THRESHOLD)
return false;
if (R2() < Constants.R2VALUE_MIN)
return false;
return true;
}
public string Formula()
{
string formula = "";
int offset = Coefficients.GetLowerBound(0) - VariableNames.GetLowerBound(0);
for (int i = Coefficients.GetLowerBound(0); i < Coefficients.GetUpperBound(0); i++)
{
formula += "(" + Coefficients[i].ToString("0.0000") + " * " + ExcelHelpers.CreateValidFormulaName(VariableNames[i - offset]) + ") + ";
// formula += "(" + Coefficients[i].ToString() + " * " + ExcelHelpers.CreateValidFormulaName(VariableNames[i - offset]) + ") + ";
}
formula += Coefficients[Coefficients.GetUpperBound(0)].ToString("0.00");
return formula;
}
public double[,] Xsplusone()
{
return DataHelper.arrayAddIdentity(Xs, 0, 1); // add on a column of ones for the intercept
}
public double[] PredictedYs()
{ // compute the predicted ys
double[] yhat = new double[N()];
double[,] xs = Xsplusone();
double[] c = Coefficients;
for (int i = 0; i < N(); i++)
{
yhat[i] = 0;
for (int j = 0; j < k() + 1; j++)
{
yhat[i] += xs[i, j] * c[j];
}
}
return yhat;
}
public double[,] CovarianceMatrix()
{
// compute the coefficient covariance matrix
double[,] twodYs = DataHelper.dbl2DArray(Ys);
double[,] XYs = DataHelper.dblarrayUnion(Xs, twodYs);
double[,] cov;
int info;
alglib.linearmodel lm;
alglib.lrreport rpt;
try
{
alglib.lrbuild(XYs, N(), k(), out info, out lm, out rpt);
cov = rpt.c;
}
catch
{
throw;
}
return cov;
}
public double[] StandardErrors()
{
// compute the x std errors and p-values
double[,] cov = CovarianceMatrix();
double[] se = new double[k()];
if (cov.GetLength(0) > 0 && cov.GetLength(1) > 0)
{
for (int j = 0; j < k(); j++)
{
se[j] = Math.Sqrt(cov[j, j]);
}
}
return se;
}
public double[] PValues()
{
double[] c = Coefficients;
double[,] cov = CovarianceMatrix();
double[] se = StandardErrors();
double[] pv = new double[k()];
if (cov.GetLength(0) > 0 && cov.GetLength(1) > 0)
{
for (int j = 0; j < k(); j++)
{
se[j] = Math.Sqrt(cov[j, j]);
try
{
pv[j] = 2 * (1 - alglib.studenttdistribution(df(), Math.Abs(c[j] / se[j])));
}
catch
{
}
}
}
return pv;
}
public string AICFormula()
{
return "";
}
//Added By Suman for SEP Validation changes
public string[] SEPValidationCheck()
{
string[] sepChk = new string[k()];
for (int cnt = 0; cnt < sepChk.Length; cnt++)
{
if (Valid() == true)
{
sepChk[cnt] = "Pass";
}
else
{
sepChk[cnt] = "Fail";
}
}
return sepChk;
}
}
这是GetHashCode():
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode();
}
我的R2():
public double R2()
{
return (1 - (ResidualSS() / TotalSS()));
}
答案 0 :(得分:3)
对于大多数类型,您不能按GetHashCode()排序,因为哈希码计算不一定按照与值相同的顺序排序。只有在值本身(例如int)时才能可靠地对GetHashCode()进行排序,但此时在获取哈希码时没有任何意义,因为您已经拥有该值。你也没有显示R2()和Valid()方法的作用,所以谁知道那里发生了什么样的不利。
EDIT(OP更新代码):
您的GetHashCode()用法绝对不可排序。也没有在double中添加布尔值。 5 + 0 vs. 2 + 1不能正确排序(假设您想要预先设置这些错误?)
只需使用((Model)x).R2()vs((Model)y).R2()作为比较,如果你想要前面的falses或trues,你可以添加如下内容:
if (x.Valid && !y.Valid)
return 1;
if (!x.Valid && y.Valid)
return -1;
//then do your R2 comparisons here.
该序言将导致非valid始终排在第一位,然后按R2排序。如果你想走另一条路,你可以倒转。
答案 1 :(得分:0)
你的.Valid()方法返回boolean,然后你去找哈希码。这是您的代码所期望的吗?
基本上,你正在做some double value + boolean.GetHashCode()
。解决方法是在右侧表达式中不使用.Valid()。单独检查。
private class R2SortHelper : System.Collections.IComparer
{
public int Compare(object x, object y)
{
Model xModel = (Model)x;
Model yModel = (Model)y;
if((Model.Valid()==true) && (yModel.Valid()==true))
{
double m1 = xModel.R2() + xModel.GetHashCode();
double m2 = yModel.R2() + yModel.GetHashCode();
return (m1 > m2) ? -1 : ((m1 < m2) ? 1 :0);
}
return 0;
}
}