Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Записка_ПСП_Градиентный спуск C# Клиент-Сервер.docx
Скачиваний:
23
Добавлен:
03.02.2019
Размер:
477.82 Кб
Скачать

Приложение а

(обязательное)

Код сервеной части

using System;

using System.Xml;

using System.Collections.Generic;

using System.Drawing;

using System.Windows.Forms;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.IO;

using System.Diagnostics;

using System.Threading;

namespace server

{

public partial class MainForm : Form

{

// Количество неизвестных

private static int n;

// Список уравнений

private String[] Urav;

public MainForm()

{

InitializeComponent();

}

// Решение выражения выражения

// при помощи обратной польской записи

double solve (String s)

{

s=s.Trim();

double rez=0.0;

if (double.TryParse(s,out rez))

{

return rez;

}

if (String.IsNullOrEmpty(s))

{

return 0.0;

}

PostfixNotationExpression post=new PostfixNotationExpression();

return (double)post.result(s);

}

// Заменяем тригонометрические функции на вычисленные выражения

private void ChangeFun (ref String s, int numFun)

{

String[] funs=new String[] {"sin","cos","ctg","tg"}; // сначала ctg, потом tg обязательно!!!!!!!!!

String fun=funs[numFun];

// Избавляемся от sin cos tg ctg

int pos=-1;

while (s.IndexOf(fun)>=0)

{

pos=s.IndexOf(fun);

int i0=pos+1;

while(s[i0]!='(') i0++;

int j=i0+1;

int level=0;

while (s[j]!=')' || level>0) {

if (s[j]=='(') { level++; j++; } else

if (s[j]==')') level--; else j++;

}

int k=i0+1;

while (s[k]==' ') k++;

// от k до j-1

string part;

part=s.Substring(k,j-1-k+1).Trim();

// Убираем лишние скобки

if (part[0]=='(' && part[part.Length-1]==')')

{

part=part.Substring(1,part.Length-2);

}

// Решаем в скобках тригонометрической функции

double v0=solve(part);

// Вычисляем значение тригонометричекой функции

double v=0.0;

switch (numFun)

{

case 0: v=Math.Sin(v0); break;

case 1: v=Math.Cos(v0); break;

case 2: v=Math.Tan(v0); break;

case 3:

{

double t=Math.Tan(v0);

if (Math.Abs(t)<0.00000001) v=1000000000; else

v=1.0/t;

};

break;

};

// Вырезаем тригонометрическую функцию от pos до j

string replace=s.Substring(pos,j-pos+1);

double dd=Math.Round(v,6);

if (dd>100000000) dd=100000000;

// Заменяем функцию на вычисленное значение

s=s.Replace(replace,dd.ToString());

}

}

// Вычисляем производуню по j-ой переменной в i-ой функции

// Значение Якобиана [i,j]

double fYakobi (int i, int j, double[,] x)

{

// Простейшая формула численного дифференцирования

double h=0.0001;

double f2=func(Urav[i],x);

x[j,0]+=h;

double f1=func(Urav[i],x);

return (f1-f2)/h;

}

// Значение функции, записанной в строке

double func (String s,double[,] x)

{

// Добавляем знак (*) между, пример: x001x005 --> x001*x005

for (int j=0; j<=9; j++)

{

while (s.IndexOf(j.ToString()+"x")>=0)

{

s=s.Replace(j.ToString()+"x",j.ToString()+"*x");

}

}

// Заменяем

s=s.Replace(")c",")*c");

s=s.Replace(")s",")*s");

s=s.Replace(")t",")*t");

s=s.Replace(")(",")*(");

// Заменяем числами, пример x001*x005 --> 1.2*4.3

for (int j=0; j<x.Length; j++)

{

String num=(j+1).ToString();

while (num.Length<3) num="0"+num;

String ss=String.Format("{0:f8}",x[j,0]);

if (x[j,0]<0)

{

s=s.Replace("x"+num,"(0,000000001"+ss+")"); // отрицательное число ставим в скобках

}

else

{

s=s.Replace("x"+num,ss);

}

}

// Замена всех тригонометрических функций

for (int j=0; j<4; j++)

{

ChangeFun (ref s, j);

}

s=s.Trim();

s=s.Replace(" "," ");

String[] mas=s.Split(' ');

double val=0.0;

foreach (String member in mas)

{

val+=solve(member.Trim());

}

return val;

}

void MainFormLoad(object sender, EventArgs e)

{

}

// Перемножение матриц

void umn (int n, int m, int k, double[,] A, double[,] B, out double[,] Rez)

{

Rez=new double[n,k];

for (int i=0; i<n; i++)

{

for (int j=0; j<k; j++)

{

Rez[i,j]=0.0;

}

};

// По всем строкам матрицы A

for (int i=0; i<n; i++)

{

for (int j=0; j<k; j++) // По всем стоблцам матрицы B

{

for (int d=0; d<m; d++) // По всем элементам строки А и столбца В

{

Rez[i,j]+=A[i,d]*B[d,j];

};

};

};

}

// Транспонирование матрицы.

private static void transp (double[,] A,out double[,] Rez)

{

Rez=new double[n,n];

for (int i=0; i<n; i++)

{

for (int j=0; j<n; j++)

{

Rez[i,j]=A[j,i];

}

};

}

// Скаляр

private static double scal(int n, double[,] s1, double[,] s2)

{

double sc=0.0;

for (int i=0; i<n; i++)

{

sc+=s1[i,0]*s2[i,0];

}

return sc;

}

void Button1Click(object sender, EventArgs e)

{

if (n<=0)

{

MessageBox.Show("Откройте файл теста");

return;

}

double[,] x0=new double[n,1];

double[,] f0=new double[n,1];

double[,] w0=new double[n,n];

double[,] x1=new double[n,1];

double[,] f1=new double[n,1];

double[,] w1=new double[n,n];

double mu;

// Задаём приближения

for (int i=0; i<n; i++) x0[i,0]=0;

for(int i=0; i<n; i++)

{

f0[i,0]=func(Urav[i],x0);

}

for (int i=0; i<n; i++)

{

for (int j=0; j<n; j++)

{

w0[i,j]=fYakobi(i,j,x0);

}

}

mu=1.0;

double[,] wt0;

double[,] wf0;

transp(w0,out wt0);

umn(n,n,1,wt0,f0,out wf0);

listBox1.Items.Clear();

listBox2.Items.Clear();

// Проверка сходимости

bool test=false;

int numiter=0; // номер итерации расходимости

// Точность решения (по невязке)

double eps=float.Parse(EditE.Text);

// флаг нахождения решения

bool solveOK=false;

// Засекаем время

System.Diagnostics.Stopwatch sw = new Stopwatch();

sw.Start();

int iter=0; // КОличество итераций

int max=1000;

// Пока невязка большая или

// количество итераций не превышено допустимого

while(iter<max && !solveOK)

{

// Расчет и вывод промежуточного решения

String sx="";

for (int i=0; i<n; i++)

{

x1[i,0]=x0[i,0]-mu*wf0[i,0];

sx+=Math.Round(x1[i,0],3)+" ";

};

listBox2.Items.Add(iter+": "+sx);

// Расчет якобиана

for (int i=0; i<n; i++)

{

for (int j=0; j<n; j++)

{

w1[i,j]=fYakobi(i,j,x1);

}

}

// решение найдено

solveOK=true;

// Расчет и вывод невязки

String s="";

for(int i=0; i<n; i++)

{

f1[i,0]=func(Urav[i],x1);

solveOK=solveOK && (Math.Abs(f1[i,0]-f0[i,0])<eps);

if (Math.Abs(f1[i,0])>=Math.Abs(f0[i,0])+eps*10 && iter>5)

{

if (!test) numiter=iter;

test=true;

}

s+=Math.Round(f1[i,0],3)+ " ";

}

listBox1.Items.Add(iter+": "+s);

// Расчет mu

double[,] wt;

double[,] wf;

double[,] wwf;

transp(w1,out wt);

umn(n,n,1,wt,f1,out wf);

umn(n,n,1,w1,wf,out wwf);

mu=scal(n,f1,wwf)/scal(n,wwf,wwf);

for (int i=0; i<n; i++)

{

f0[i,0]=f1[i,0];

x0[i,0]=x1[i,0];

wf0[i,0]=wf[i,0];

for (int j=0; j<n; j++)

{

w0[i,j]=w1[i,j];

}

}

// Счетчик итераций

iter++;

}

sw.Stop();

label5.Text="Время работы: "+sw.ElapsedMilliseconds.ToString()+ "мс";

// Выделяем последние расчетные данные в списке

listBox1.SelectedIndex=listBox1.Items.Count-1;

listBox2.SelectedIndex=listBox2.Items.Count-1;

if (test)

{

label3.Text=" С итерации № "+numiter+" обнаружена расходимость.";

}

else

{

label3.Text="Приближенное решение найдено";

}

}

void ОткрытьТестToolStripMenuItemClick(object sender, EventArgs e)

{

if (openFileDialog1.ShowDialog()==DialogResult.OK)

{

// Загружаем

StreamReader sr=new StreamReader(openFileDialog1.FileName);

String txt=sr.ReadToEnd().Trim();

sr.Close();

//Замянем

txt=txt.Replace("\r\n","\n");

Urav=txt.Split('\n');

n=Urav.Length;

listBox3.Items.Clear();

foreach(String s in Urav)

listBox3.Items.Add(s);

}

}

void ФайлToolStripMenuItemClick(object sender, EventArgs e)

{

}

void Button2Click(object sender, EventArgs e)

{

if (n<=0)

{

MessageBox.Show("Откройте файл теста");

return;

}

XmlTextReader reader = new XmlTextReader ("ip_address.xml");

String[] ip=new String[2];

int num=0;

int[] port=new int[2];

int nom=0;

while (reader.Read())

{

if (reader.NodeType==XmlNodeType.Element && reader.Name.Equals("ip"))

{

reader.Read();

ip[num]=reader.Value;

num++;

}

if (reader.NodeType==XmlNodeType.Element && reader.Name.Equals("port"))

{

reader.Read();

port[nom]=int.Parse(reader.Value);

nom++;

}

}

IPHostEntry ipHost1 = Dns.GetHostEntry(ip[0]);

IPHostEntry ipHost2 = Dns.GetHostEntry(ip[1]);

IPAddress ipAddr1=ipHost1.AddressList[0];

IPAddress ipAddr2=ipHost2.AddressList[0];

// Посылаем размерность

byte[] ans=new byte[1];

byte[] sendByte=new byte[2];

sendByte[0]=0;

sendByte[1]=(byte)n;

SendMessageFromSocket(ipAddr1,port[0], sendByte, ref ans);

sendByte[0]=1;

SendMessageFromSocket(ipAddr2,port[1], sendByte, ref ans);

// Посылаем уравнения

for (int i=0; i<n; i++)

{

sendByte=Encoding.Unicode.GetBytes(Urav[i]);

SendMessageFromSocket(ipAddr1,port[0], sendByte, ref ans);

SendMessageFromSocket(ipAddr2,port[1], sendByte, ref ans);

}

double[,] x0=new double[n,1];

double[,] f0=new double[n,1];

double[,] w0=new double[n,n];

double[,] x1=new double[n,1];

double[,] f1=new double[n,1];

double[,] w1=new double[n,n];

double mu;

// Задаём приближения

for (int i=0; i<n; i++) x0[i,0]=0;

for(int i=0; i<n; i++)

{

f0[i,0]=func(Urav[i],x0);

}

for (int i=0; i<n; i++)

{

for (int j=0; j<n; j++)

{

w0[i,j]=fYakobi(i,j,x0);

}

}

mu=1.0;

double[,] wt0;

double[,] wf0;

transp(w0,out wt0);

umn(n,n,1,wt0,f0,out wf0);

listBox1.Items.Clear();

listBox2.Items.Clear();

// Проверка сходимости

bool test=false;

int numiter=0; // номер итерации расходимости

// Точность решения (по невязке)

double eps=float.Parse(EditE.Text);

// флаг нахождения решения

bool solveOK=false;

// Засекаем время

System.Diagnostics.Stopwatch sw = new Stopwatch();

sw.Start();

int iter=0; // КОличество итераций

int max=1000;

// Пока невязка большая или

// количество итераций не превышено допустимого

while(iter<max && !solveOK)

{

// Расчет и вывод промежуточного решения

String sx="";

for (int i=0; i<n; i++)

{

x1[i,0]=x0[i,0]-mu*wf0[i,0];

sx+=Math.Round(x1[i,0],3)+" ";

};

listBox2.Items.Add(iter+": "+sx);

// Расчет якобиана - Параллельно

// Посылаем x1 на оба компьютера

double[] mas=new double[n];

for (int v=0; v<n; v++) mas[v]=x1[v,0];

sendByte=new byte[mas.Length*8];

Buffer.BlockCopy(mas, 0, sendByte, 0, sendByte.Length);

SendMessageFromSocket(ipAddr1,port[0], sendByte, ref ans);

SendMessageFromSocket(ipAddr2,port[1], sendByte, ref ans);

// Получаем Якобиан по частям

int middle=n/2;

for (int i=0; i<middle; i++)

{

byte[] question=new byte[2];

question[0]=1;

question[1]=(byte)i;

byte[] getByte=new byte[sendByte.Length];

SendMessageFromSocket(ipAddr1,port[0], question, ref getByte);

for(int v = 0 ; v < n ; v++)

{

w1[i,v] = BitConverter.ToDouble(getByte, v * 8);

}

}

for (int i=middle; i<n; i++)

{

byte[] question=new byte[2];

question[0]=1;

question[1]=(byte)i;

byte[] getByte=new byte[sendByte.Length];

SendMessageFromSocket(ipAddr2,port[1], question, ref getByte);

for(int v = 0 ; v < n ; v++)

{

w1[i,v] = BitConverter.ToDouble(getByte, v * 8);

}

}

listBox3.Items.Add("Полученный Якобиан по частям:");

// Вывод Якобиана

for (int i=0; i<n; i++)

{

String s3="";

for (int j=0; j<n; j++)

{

s3+=Math.Round(w1[i,j],5)+" ";

}

listBox3.Items.Add(s3);

}

// решение найдено

solveOK=true;

// Расчет и вывод невязки

String s="";

for(int i=0; i<n; i++)

{

f1[i,0]=func(Urav[i],x1);

solveOK=solveOK && (Math.Abs(f1[i,0]-f0[i,0])<eps);

if (Math.Abs(f1[i,0])>=Math.Abs(f0[i,0])+eps*10 && iter>5)

{

if (!test) numiter=iter;

test=true;

}

s+=Math.Round(f1[i,0],3)+ " ";

}

listBox1.Items.Add(iter+": "+s);

// Расчет mu

double[,] wt;

double[,] wf;

double[,] wwf;

transp(w1,out wt);

umn(n,n,1,wt,f1,out wf);

umn(n,n,1,w1,wf,out wwf);

mu=scal(n,f1,wwf)/scal(n,wwf,wwf);

for (int i=0; i<n; i++)

{

f0[i,0]=f1[i,0];

x0[i,0]=x1[i,0];

wf0[i,0]=wf[i,0];

for (int j=0; j<n; j++)

{

w0[i,j]=w1[i,j];

}

}

// Счетчик итераций

iter++;

// Посылаем контрольный байт

byte[] ans3=new byte[1];

byte[] sendByte3=new byte[2];

if (iter<max && !solveOK)

sendByte3[0]=0; // 0 - продолжаем

else

sendByte3[0]=3; // 3 - конец

sendByte3[1]=0;

SendMessageFromSocket(ipAddr1,port[0], sendByte3, ref ans3);

SendMessageFromSocket(ipAddr2,port[1], sendByte3, ref ans3);

}

// посленяя запись

listBox3.SelectedIndex=listBox3.Items.Count-1;

sw.Stop();

label6.Text="Время работы: "+sw.ElapsedMilliseconds.ToString()+ "мс";

// Выделяем последние расчетные данные в списке

listBox1.SelectedIndex=listBox1.Items.Count-1;

listBox2.SelectedIndex=listBox2.Items.Count-1;

if (test)

{

label3.Text=" С итерации № "+numiter+" обнаружена расходимость.";

}

else

{

label3.Text="Приближенное решение найдено";

}

}

static void SendMessageFromSocket(IPAddress ipAddr, int port, byte[] sendBytes, ref byte[] getBytes)

{

// Соединяемся с удаленным устройством

// Устанавливаем удаленную точку для сокета

IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, port);

Socket sender = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

// Соединяем сокет с удаленной точкой

sender.Connect(ipEndPoint);

// Отправляем данные через сокет

int bytesSent = sender.Send(sendBytes);

// Получаем ответ

int bytesRec = sender.Receive(getBytes);

// Освобождаем сокет

sender.Shutdown(SocketShutdown.Both);

sender.Close();

}

}

}