稳健估计

测量中粗差不可避免,但是常用的最小二乘估计却不具备抗干扰的能力,对含粗差的观测量相当敏感,因此如果拿最小二乘原理去处理韩有粗差的数据,会造成严重的后果。

在现代广义平差测量中,常常使用稳健估计来探测和处理粗差,其中最经常用的就是就是M估计,这里p函数我选择Huber函数,来实现。

具体原理:

 

程序中我使用了我前两篇博客中的矩阵库和间接平差类。

 

 

using CMath;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Adjust
{
    /// <summary>
    /// 稳健估计,M估计
    /// </summary>
    public static class Huber
    {
        /// <summary>
        /// 得到粗差剔除后的改正值
        /// </summary>
        /// <param name="fun">观测方程</param>
        /// <param name="e">迭代精度</param>
        /// /// <param name="size">中误差调整系数</param>
        /// <returns>得到粗差剔除后的改正值</returns>
        public static Matrix GetHuber(LinearEquation fun,double size=1, double e=0.1)
        {
            //构造一个参数矩阵,默认为0
            double[,] xite = new double[fun.B.Cols, 1];
            for (int i = 0; i < xite.GetLength(0); i++)
            {
                xite[i,0] = 0.0;
            }
            Matrix Xite = new Matrix(xite);
            Matrix X = fun.GetNW();
            //构造一个精度矩阵
            double[,] eite=new double[fun.B.Cols,1];
             for (int i = 0; i < eite.GetLength(0); i++)
            {
                xite[i,0] = e;
            }
            Matrix Eite = new Matrix(xite);
            //开始迭代
            while (Matrix.MAbs(X - Xite) > Eite)
            {
                X = Xite;
                bool iserror = false;
                //包含含有粗差的索引
                List<int> index = new List<int>();
                //检测是否有粗差
                //可能含有多个粗差
                try
                {
                    for (int i = 0; i < fun.GetV().Rows; i++)
                    {
                        if (Math.Abs(fun.GetV()[i, 0]) > size * fun.GetSigam())
                        {
                            iserror = false;
                            index.Add(i);
                        }
                    }
                }
                catch
                {
                    throw new Exception("误差方程构造错误");
                }
                //未含有粗差
                if (iserror) break;
                //含有粗差
                else
                {
                    //调整观测权
                    //需要调整多个
                    for (int i = 0; i < index.Count; i++)
                    {    
                        //这里使用Huber来改正权
                        fun.P[index[i], index[i]] = size*fun.GetSigam() / Math.Abs(fun.GetV()[index[i],0]);
                    }
                }
                //重新解算
                Xite = fun.GetNW();
            }
            return Xite;
        }
    }
   
}

 

posted @ 2016-10-18 08:49  啊王会  阅读(2488)  评论(0编辑  收藏  举报