public MinMaxRule(SetOfSigns _X, SetOfSigns _Y) { X = _X; Y = _Y; x0 = X[0]; y0 = Y[0]; }
public static vectorObject[] GetNewCoords(vectorObject x, vectorObject y) { vectorObject[] be = new vectorObject[2]; be[0] = ReCoord2D(x); be[1] = ReCoord2D(y); return be; }
/// <summary> Определяет координатную четверть</summary> public static vectorObject GetCoords2D(vectorObject vec) { vectorObject tmp = new vectorObject(2); tmp[0] = vec[0] - Boards[0].Width / 2; tmp[1] = vec[1] - Boards[0].Height / 2; return tmp; }
/// <summary> Определяет координатную четверть</summary> public static vectorObject GetCoords2D(float x, float y) { vectorObject tmp = new vectorObject(2); tmp[0] = x - Boards[0].Width / 2; tmp[1] = y - Boards[0].Height / 2; return tmp; }
public vectorObject this[int ObjN] { get { return objects[ObjN]; } set { if (ObjN >= count) { vectorObject[] New = new vectorObject[ObjN+1]; for(int i=0; i<count; i++) { New[i] = objects[i]; } objects = New; count = ObjN + 1; } objects[ObjN] = value; } }
public static vectorObject[] GetNewCoords(vectorObject w, vectorObject x1, vectorObject y1) { vectorObject p = new vectorObject((x1[0] + y1[0]) / 2, (x1[1] + y1[1]) / 2); float A = y1[0] - x1[0]; float B = y1[1] - x1[1]; float C = -(A * p[0] + B * p[1]); float[] p4 = new float[2]; p4[0] = -Utilities.Boards[0].Width / 2; p4[1] = -(A * p4[0] + C) / B; float[] p3 = { Utilities.Boards[0].Width / 2, -(A * (Utilities.Boards[0].Width / 2) + C) / B }; vectorObject[] be = new vectorObject[2]; be[0] = new vectorObject(p3); be[1] = new vectorObject(p4); return be; }
//Критерий останова private bool StoppingCriterion(vectorObject x1, vectorObject y1, double gamma) { Utilities.Message("Проверяем критерий останова"); Thread.Sleep(1500); double p = (x1-y1).Norm(); double min = Math.Abs((W * X[0]) / W.Norm()); for (int i = 0; i < X.Count; i++) { if (Math.Abs((W * X[i]) / W.Norm()) < min) { min = Math.Abs((W * X[i]) / W.Norm()); } } for (int i = 0; i < Y.Count; i++) { if (Math.Abs((W * Y[i]) / W.Norm()) < min) { min = Math.Abs((W * Y[i]) / W.Norm()); } } return (2*min>=gamma*p); }
//Вычисляем коэфициенты по т. Куна-Такера private void KuhnTucker(ref float l1, ref float l2, vectorObject xp, vectorObject yq) { #region объявление и инициализация переменных float a = (y0 - x0) * (xp - x0); float b = (y0 - yq) * (y0 - yq); float c = (y0 - x0) * (y0 - yq); float d = (xp - x0) * (y0 - yq); float e = (xp - x0) * (xp - x0); float f = (y0 - xp) * (y0 - yq); float h = (yq - x0) * (xp - x0); #endregion //36 if ((b * e) - (d * d) != 0) { //37 l1 = ((a * b) - (c * d)) / ((b * e) - (d * d)); l2 = ((c * e) - (a * d)) / ((b * e) - (d * d)); if (l1<=0) { //38 l2 = c / b; } else { if (l1>=1) { //41 l2 = f / b; } } } else { l1 = 0; l2 = c / b; } //40 if (l2 <= 0) { //42 l1 = a / e; } else { //43 if (l2>=1) { //45 l1 = h / e; } } //55 if (l1 <= 0) { //56 l1 = 0; } else { if (l1 > 1) { l1 = 1; } } //58 if (l2<=0) { l2 = 0; } else { if (l2>1) { l2 = 1; } } //if (!((l1 > 0 & l1 < 1) & (l2 > 0 & l2 < 1))) //{ // KuhnTucker(ref l1, ref l2, xp, yq); //} }
//Проверка является ли гиперплоскость разделяющей private bool IsRightPlane(vectorObject x1, vectorObject y1) { Utilities.Message("Проверяем является ли правило разделяющим"); Thread.Sleep(1500); for (int i = 0; i < X.Count; i++) { if ((W * X[i] - W * (x1 + y1) / 2) < 0) return false; } for (int i = 0; i < Y.Count; i++) { if ((W * Y[i] - W * (x1 + y1) / 2) > 0) return false; } return true; }
//Поиск минимального расстояния между прямыми xp-x0 и yq-y0 private void FindMinLength(ref vectorObject xp, ref vectorObject yq, ref vectorObject x1, ref vectorObject y1) { float l1 = 0; float l2 = 0; KuhnTucker(ref l1, ref l2, xp, yq); x1 = x0 + l1 * (xp - x0); y1 = y0 + l2 * (yq - y0); }
/// <summary> Превращает нормальные координаты в координаты для отрисовки </summary> public static vectorObject ReCoord2D(vectorObject OldCoord) { vectorObject NewCoord = new vectorObject(OldCoord.Size); NewCoord[0] = OldCoord[0]; if (OldCoord[1] > 0) NewCoord[1] = -OldCoord[1]; else NewCoord[1] = -OldCoord[1]; return NewCoord; }
public vectorObject Normalized() { vectorObject tmp = new vectorObject(this.coords); float norm = tmp.Norm(); for (int i = 0; i < n; i++) { tmp[i] = tmp[i] / norm; } return tmp; }
public static vectorObject operator *(float alpha, vectorObject v) { vectorObject tmp = new vectorObject(v.n); for (int i = 0; i < v.n; i++) { tmp[i] = alpha * v[i]; } return tmp; }
public static SetOfSigns[] ReadTask(out int cellsize) { SetOfSigns[] imgs; OpenFileDialog of = new OpenFileDialog(); of.Title = "Выберите файл"; of.Filter = "Текстовые файлы|*.txt"; cellsize = 1; if (of.ShowDialog() == DialogResult.OK) { TextReader tr = new StreamReader(of.FileName); cellsize = Int32.Parse(NextString(tr)); int n = Int32.Parse(NextString(tr)); imgs = new SetOfSigns[n]; for (int i = 0; i < n; i++) { string tmp = NextString(tr); string[] objs = tmp.Split(';'); imgs[i] = new SetOfSigns(objs.Count() - 1); for (int j = 0; j < objs.Count() - 1; j++) { string[] coords = objs[j].Split(','); float[] crds = new float[coords.Count()]; for (int k = 0; k < crds.Count(); k++) { crds[k] = float.Parse(coords[k]); } imgs[i][j] = new vectorObject(crds); } } tr.Close(); return imgs; } return null; }
public static vectorObject LineCross(vectorObject x0, vectorObject y0, vectorObject p) { float A = y0[0] - x0[0]; float B = y0[1] - x0[1]; float C = -(A * p[0] + B * p[1]); float[] p4 = new float[2]; p4[0] = -Utilities.Boards[0].Width/2; p4[1] = -(A * p4[0] + C) / B; float[] p1 = {x0[0], x0[1]}; float[] p2 = {y0[0], y0[1]}; float[] p3 = { Utilities.Boards[0].Width / 2, -(A * (Utilities.Boards[0].Width / 2) + C) / B }; vectorObject rez = new vectorObject(SegmentCross(p1, p2, p3, p4)); return rez; }
public void BuildRule() { Utilities.Boards.Add(new GraphicsBoard(Utilities.Boards[0].Width, Utilities.Boards[0].Height, Utilities.Boards[0].Graphics)); //инициализируем класс-список объектов текущего состояния экрана Utilities.Boards[Utilities.Boards.Count - 1].AddElem(Utilities.Boards[0]); //Добавляем на экран отображение точек множеств Pen dpen = new Pen(Brushes.Black, 2); dpen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; //пунктирная линия vectorObject x1; vectorObject y1; vectorObject[] XXPcrds = new vectorObject[2]; vectorObject[] YYQcrds = new vectorObject[2]; vectorObject[] XYcrds1 = new vectorObject[2]; vectorObject[] G = new vectorObject[2]; while (true) { vectorObject xp = null; vectorObject yq = null; FindMaxPrs(ref xp, ref yq); if (xp == x0 || yq == y0) { try { Utilities.Message("Нет новых точек"); Utilities.Boards.Add(new GraphicsBoard(Utilities.Boards[0].Width, Utilities.Boards[0].Height, Utilities.Boards[0].Graphics)); //инициализируем класс-список объектов текущего состояния экрана Utilities.Boards[Utilities.Boards.Count - 1].AddElem(Utilities.Boards[0]); //Добавляем на экран отображение точек множеств Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(XXPcrds[0][0], XXPcrds[0][1], new Pen(Brushes.Green, 3)), new Point2f(XXPcrds[1][0], XXPcrds[1][1], new Pen(Brushes.Green, 3)))); //прямая (x0,xp) Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(YYQcrds[0][0], YYQcrds[0][1], new Pen(Brushes.Green, 3)), new Point2f(YYQcrds[1][0], YYQcrds[1][1], new Pen(Brushes.Green, 3)))); //прямая (y0,yq) Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(XYcrds1[0][0], XYcrds1[0][1], new Pen(Brushes.Green, 3)), new Point2f(XYcrds1[1][0], XYcrds1[1][1], new Pen(Brushes.Green, 3)))); Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, new Pen(Brushes.Black, 3), new Point2f(G[0][0], G[0][1]), new Point2f(G[1][0], G[1][1]))); Utilities.Boards[Utilities.Boards.Count - 1].Draw(Utilities.Boards[0].cellsize);//прямая (y1,x1) Utilities.drawDone.Set(); Thread.Sleep(1500); } catch(Exception e) { Utilities.Message("Нет точек для построения симплекса"); } break; } x1 = new vectorObject(x0.Size); y1 = new vectorObject(y0.Size); FindMinLength(ref xp, ref yq, ref x1, ref y1); W = FindHyperplane(x1, y1); if (IsSeparating(delta)) { if (IsRightPlane(x1, y1)) { if (StoppingCriterion(x1, y1, gamma)) { Utilities.Message("Найдено линейное разделяющее правило"); XXPcrds[0] = x0; XXPcrds[1] = xp; YYQcrds[0] = y0; YYQcrds[1] = yq; XYcrds1[0] = x1; XYcrds1[1] = y1; G = Utilities.GetNewCoords(W, x1, y1); if (Utilities.Boards[0].cellsize > 1) { XXPcrds = Utilities.GetNewCoords(x0, xp); //Получаем координаты для отрисовки YYQcrds = Utilities.GetNewCoords(y0, yq); XYcrds1 = Utilities.GetNewCoords(x1, y1); G = Utilities.GetNewCoords2(W, x1, y1); } Utilities.Boards.Add(new GraphicsBoard(Utilities.Boards[0].Width, Utilities.Boards[0].Height, Utilities.Boards[0].Graphics)); //инициализируем класс-список объектов текущего состояния экрана Utilities.Boards[Utilities.Boards.Count - 1].AddElem(Utilities.Boards[0]); //Добавляем на экран отображение точек множеств Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(XXPcrds[0][0], XXPcrds[0][1], new Pen(Brushes.Green, 3)), new Point2f(XXPcrds[1][0], XXPcrds[1][1], new Pen(Brushes.Green, 3)))); //прямая (x0,xp) Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(YYQcrds[0][0], YYQcrds[0][1], new Pen(Brushes.Green, 3)), new Point2f(YYQcrds[1][0], YYQcrds[1][1], new Pen(Brushes.Green, 3)))); //прямая (y0,yq) Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(XYcrds1[0][0], XYcrds1[0][1], new Pen(Brushes.Green, 3)), new Point2f(XYcrds1[1][0], XYcrds1[1][1], new Pen(Brushes.Green, 3)))); Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, new Pen(Brushes.Black, 3), new Point2f(G[0][0], G[0][1]), new Point2f(G[1][0], G[1][1]))); Utilities.Boards[Utilities.Boards.Count - 1].Draw(Utilities.Boards[0].cellsize);//прямая (y1,x1) Utilities.drawDone.Set(); Thread.Sleep(1500); Utilities.drawing = false; Thread.Sleep(1500); break; } } XXPcrds[0] = x0; XXPcrds[1] = xp; YYQcrds[0] = y0; YYQcrds[1] = yq; XYcrds1[0] = x1; XYcrds1[1] = y1; G = Utilities.GetNewCoords(W, x1, y1); if (Utilities.Boards[0].cellsize > 1) { XXPcrds = Utilities.GetNewCoords(x0, xp); //Получаем координаты для отрисовки YYQcrds = Utilities.GetNewCoords(y0, yq); XYcrds1 = Utilities.GetNewCoords(x1, y1); G = Utilities.GetNewCoords2(W, x1, y1); } Utilities.Boards.Add(new GraphicsBoard(Utilities.Boards[0].Width, Utilities.Boards[0].Height, Utilities.Boards[0].Graphics)); //инициализируем класс-список объектов текущего состояния экрана Utilities.Boards[Utilities.Boards.Count - 1].AddElem(Utilities.Boards[0]); //Добавляем на экран отображение точек множеств Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(XXPcrds[0][0], XXPcrds[0][1], new Pen(Brushes.Green, 3)), new Point2f(XXPcrds[1][0], XXPcrds[1][1], new Pen(Brushes.Green, 3)))); //прямая (x0,xp) Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(YYQcrds[0][0], YYQcrds[0][1], new Pen(Brushes.Green, 3)), new Point2f(YYQcrds[1][0], YYQcrds[1][1], new Pen(Brushes.Green, 3)))); //прямая (y0,yq) Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(XYcrds1[0][0], XYcrds1[0][1], new Pen(Brushes.Green, 3)), new Point2f(XYcrds1[1][0], XYcrds1[1][1], new Pen(Brushes.Green, 3)))); Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, new Pen(Brushes.Black, 3), new Point2f(G[0][0], G[0][1]), new Point2f(G[1][0], G[1][1]))); Utilities.Boards[Utilities.Boards.Count - 1].Draw(Utilities.Boards[0].cellsize);//прямая (y1,x1) Utilities.drawDone.Set(); Thread.Sleep(1500); x0 = x1; y0 = y1; } else { Utilities.Message("Множества линейно не разделимы"); Utilities.drawing = false; break; } if (!Utilities.multi) { Utilities.nextStep.WaitOne(); Utilities.nextStep.Reset(); } } }
public static vectorObject[] GetNewCoords2(vectorObject w, vectorObject x1, vectorObject y1) { vectorObject[] be = new vectorObject[2]; be[0] = x1 + y1; float a = (w * be[0]) / 2; float yk = (a - w[0] * Boards[0].Width) / w[1]; float y0 = a / w[1]; be[0] = new vectorObject(0, y0); be[1] = new vectorObject(Boards[0].Width, yk); be[0] = ReCoord2D(be[0]); be[1] = ReCoord2D(be[1]); return be; }
public static vectorObject operator -(vectorObject v1, vectorObject v2) { vectorObject tmp = new vectorObject(v1.n); for (int i = 0; i < v1.n; i++) { tmp[i] = v1[i] - v2[i]; } return tmp; }
//Поиск гиперплоскости private vectorObject FindHyperplane(vectorObject x1, vectorObject y1) { Utilities.Message("Ищем результирующий направляющий вектор W"); Thread.Sleep(1500); vectorObject _w = new vectorObject(x1.Size); _w = x1 - y1; return _w.Normalized(); }
public vectorObject(vectorObject v) { coords = v.coords; n = v.n; }
//Поиск Xp и Yq private void FindMaxPrs(ref vectorObject xp, ref vectorObject yq) { Utilities.Message("Ищем одномерные симплексы"); Pen dpen = new Pen(Brushes.Black, 2); dpen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; //пунктирная линия double maxX = 0; double maxY = 0; for (int i = 0; i < Math.Max(X.Count, Y.Count); i++) { Utilities.Boards.Add(new GraphicsBoard(Utilities.Boards[0].Width, Utilities.Boards[0].Height, Utilities.Boards[0].Graphics)); //инициализируем класс-список объектов текущего состояния экрана Utilities.Boards[Utilities.Boards.Count - 1].AddElem(Utilities.Boards[0]); //Добавляем на экран отображение точек множеств vectorObject Xcrds = x0; vectorObject Ycrds = y0; if (Utilities.Boards[0].cellsize > 1) { Xcrds = Utilities.ReCoord2D(x0); //Получаем координаты для отрисовки Ycrds = Utilities.ReCoord2D(y0); } Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Point2f(Xcrds[0], Xcrds[1], new Pen(Brushes.HotPink, 3))); //добавляем на экран точку x0 Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Point2f(Ycrds[0], Ycrds[1], new Pen(Brushes.HotPink, 3))); //добавляем на экран точку y0 Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, new Pen(Brushes.Orchid, 2), new Point2f(Xcrds[0], Xcrds[1]), new Point2f(Ycrds[0], Ycrds[1]))); // рисуем линию от x0 до y0 if (i < X.Count) { if ((X[i] - x0) * (y0 - x0) > maxX) { maxX = (X[i] - x0) * (y0 - x0); xp = X[i]; } if (x0 != X[i]) { vectorObject crds = MathUtils.LineCross(x0, y0, X[i]); vectorObject tmp = X[i]; if (Utilities.Boards[0].cellsize > 1) { crds = Utilities.ReCoord2D(crds); tmp = Utilities.ReCoord2D(X[i]); } Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, new Pen(Brushes.Black, 2), new Point2f(Xcrds[0], Xcrds[1]), new Point2f(tmp[0], tmp[1])));//рисуем линию от x0 до Xi Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(tmp[0], tmp[1]), new Point2f(crds[0], crds[1])));//рисуем линию от Xi до проекции Xi на прямую (x0,y0) } } if (i < Y.Count) { if ((Y[i] - y0) * (x0 - y0) > maxY) { maxY = (Y[i] - y0) * (x0 - y0); yq = Y[i]; } if (y0 != Y[i]) { vectorObject crds = MathUtils.LineCross(x0, y0, Y[i]); vectorObject tmp = Y[i]; if (Utilities.Boards[0].cellsize > 1) { crds = Utilities.ReCoord2D(crds); tmp = Utilities.ReCoord2D(Y[i]); } Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, new Pen(Brushes.Black, 2), new Point2f(Ycrds[0], Ycrds[1]), new Point2f(tmp[0], tmp[1])));//рисуем линию от y0 до Yi Utilities.Boards[Utilities.Boards.Count - 1].AddElem(new Line(Utilities.Boards[0].Graphics, dpen, new Point2f(tmp[0], tmp[1]), new Point2f(crds[0], crds[1])));//рисуем линию от Yi до проекции Yi на прямую (x0,y0) } } try { int f = xp.Size; } catch(Exception e) { xp = x0; } try { int f = yq.Size; } catch(Exception e) { yq = y0; } Utilities.Boards[Utilities.Boards.Count - 1].Draw(Utilities.Boards[0].cellsize); Utilities.drawDone.Set(); Thread.Sleep(1000); if (!Utilities.multi) { Utilities.nextStep.WaitOne(); //Utilities.nextStep.Reset(); } } Utilities.Message(""); }