< -->

Program _Approc_;{Аппроксимация функций методом наименьших квадратов}
{$E-,N+,G+,D+}
Uses Graph, CRT;
type
  Tkf = array [0..6] of Extended;
  Real = Extended;
type
 Sto = array [ 1..70 ] of Extended;
const
  n = 10;
  x0 : Extended = 1.0;
  xn : Extended = 4.0;
  Yb : Integer = 464;
  Eps : Extended = 1.0E-14;
  dtb : Extended = 1.0E-4;
  HotKey : Boolean = False;
var
  mm, kk : Byte;
  Dr, R, e : Integer;
  y : array [0..n] of Extended;
  dx, ymax, ymin, x : Extended;
  OldInt09h : Pointer;
  Pkf : ^Tkf;
 A          : array [ 1..70 ] of Sto;{Массив }
 B          : Sto ;
var
  i, j : Longint;
{  d, g, p, q, m, k, l : Extended;}
Function f(x, d, g, p, q, m, k, l : Extended):Extended;{Сама функция}
begin
  f := (d+exp((p*x+q)*ln(x)))*exp(m*x*x+k*x+l);
end;
Procedure Swap(p, q: Byte);
var
 j : Byte;
 X : Real;
begin
 for j:=1 to n do
   begin
    X := A[p,j];
    A[p,j] := A[q,j];
    A[q,j] := X;
   end;
   X := B[p];
   B[p] := B[q];
   B[q] := X;
end;
Procedure Divid(p : Byte; k : Real);
var
 j : Byte;
begin
 for j := 1 to n do
  begin
   A[p, j] := A[p, j] / k;
   if Abs(A[p, j]) <1.0E-10 then   {Иначе возможен неправильный результат}
       A[p, j] := 0.0;
  end;
  B[p] := B[p] / k;
  if Abs(B[p]) <1.0E-10 then
       B[p] := 0.0;
end;

Procedure Sub(p, q : Byte);
var
 j : Byte;
begin
 for j := 1 to n do
  begin
   A[p, j] := A[p, j] - A[q, j];
   if Abs(A[p, j]) <1.0E-10 then   {Иначе возможен неправильный результат}
      A[p, j] := 0.0;
  end;
   B[p] := B[p] - B[q];
  if Abs(B[p]) <1.0E-10 then
     B[p] := 0.0;
end;

Function CheckNullStr(p : Byte): Boolean;
var
 i : Byte;
 k : Real;
begin
 k := 0;
 for i := 1 to n do
   k:=k + Abs (A[p, i]);
 CheckNullStr := ((k=0) and (B[p]=0));
end;

Function BadStr(p : Byte) : Boolean;
var
 i : Byte;
 k : Real;
begin
 k := 0;
 for i := 1 to n do
   k:=k + Abs (A[p, i]);
 BadStr := ((k=0) and (B[p]<>0));
end;

Procedure KillNullStr(r : Byte);
begin
 Swap(r, mm);
 dec(mm);
end;

Function IsZeroDiag : Boolean;
var
 i : Byte;
 q : Boolean;
begin
 q := false;
 for i := 1 to mm do
   q := q or (A[i,i] = 0) ;
 IsZeroDiag := q;
end;

Procedure FindNZD ;
var
 i : Byte;
begin
 for i := kk+1 to mm do
   if A[i,kk] <> 0.0 then
     begin
       Swap(kk, i);
     end;
end;
Procedure SolveMatr;
var
  i : Byte;
Label
  Loop{:Word};
begin
kk := 1;
Loop:
 While kk <= mm do     {???}
   begin
    for i := 1 to mm do
      if not BadStr(i) then
         begin
           if CheckNullStr(i) then
             begin
               KillNullStr(i);
               goto loop;
             end;
         end
     else ViewResult(0);
  FindNZD;
      p:=0;
      for i := kk to n do
                    if A[k,i] = 0 then inc(p)
                                  else Break;
      for i := 1 to m do
        if A[i,k+p]<>0 then
          Divid(i, A[i,k+p]);
      for i :=1 to m do
        if (i<>(k+p)) and (A[i,k+p]<>0.0) then
          Sub(i,k+p);
    inc(kk);
   end;
  for i:=1 to m do if A[i,i]<>0 then
    Divid(i,A[i,i]);
 i :=1;
 While i <= m do
   begin
    if BadStr(i) then ViewResult(0);
    if CheckNullStr(i) then KillNullStr(i);
    inc(i);
   end;
end;
{Function S(d, g, p, q, m, k, l : Extended) : Extended; {Сумма квадратов отклонений}
{var
  i : Longint;
  Si : Extended;
begin
  Si := 0.0;
  for i := 0 to n do
    Si := Si + sqr(f(x0+dx*i, d, g, p, q, m, k, l)-y[i]);
  S := Si;
end;
{Procedure Approch(var d, g, p, q, m, k, l : Extended);
var
  i : Longint;
  t, dt : Extended;
  d1, g1, p1, q1, m1, k1, l1 : Extended;
begin

  dt := dtb;
  t := l;
  Write('l...');
  if  (S(d, g, p, q, m, k, t+dt)-S(d, g, p, q, m, k, t)>0.0) then dt := -dt;
  While (S(d, g, p, q, m, k, t+dt)-S(d, g, p, q, m, k, t)<0.0) do
    t := t + dt;
  l1 := t;
  WriteLn(t:5:5);

  dt := dtb;
  t := k;
  Write('k...');
  if  (S(d, g, p, q, m, t+dt, l)-S(d, g, p, q, m, t, l)>0.0) then dt := -dt;
  While (S(d, g, p, q, m, t+dt, l)-S(d, g, p, q, m, t, l)<0.0) do
    t := t + dt;
  k1 := t;
  WriteLn(t:5:5);

  dt := dtb;
  t := m;
  Write('m...');
  if  (S(d, g, p, q, t+dt, k, l)-S(d, g, p, q, t, k, l)>0.0) then dt := -dt;
  While (S(d, g, p, q, t+dt, k, l)-S(d, g, p, q, t, k, l)<0.0) do
    t := t + dt;
  m1 := t;
  WriteLn(t:5:5);

  dt := dtb;
  t := q;
  Write('q...');
  if  (S(d, g, p, t+dt, m, k, l)-S(d, g, p, t, m, k, l)>0.0) then dt := -dt;
  While (S(d, g, p, t+dt, m, k, l)-S(d, g, p, t, m, k, l)<0.0) do
    t := t + dt;
  q1 := t;
  WriteLn(t:5:5);

  dt := dtb;
  t := p;
  Write('p...');
  if  (S(d, g, t+dt, q, m, k, l)-S(d, g, t, q, m, k, l)>0.0) then dt := -dt;
  While (S(d, g, t+dt, q, m, k, l)-S(d, g, t, q, m, k, l)<0.0) do
    t := t + dt;
  p1 := t;
  WriteLn(t:5:5);

  dt := dtb;
  t := g;
  WriteLn('g...');
  if  (S(d, t+dt, p, q, m, k, l)-S(d, t, p, q, m, k, l)>0.0) then dt := -dt;
  While (S(d, t+dt, p, q, m, k, l)-S(d, t, p, q, m, k, l)<0.0) do
  begin
    t := t + dt;
    GotoXY(1, WhereY);
    Write(S(d, t+dt, p, q, m, k, l)-S(d, t, p, q, m, k, l) :5 :5, ' ', t :5 :5, '            ');
  end;
  g1 := t;
  WriteLn(t:5:5);

  dt := dtb;
  t := d;
  WriteLn('d...');
  if  (S(t+dt, g, p, q, m, k, l)-S(t, g, p, q, m, k, l)>0.0) then dt := -dt;
  While (S(t+dt, g, p, q, m, k, l)-S(t, g, p, q, m, k, l)<0.0) do
  begin
    t := t + dt;
    GotoXY(1, WhereY);
    Write(S(t+dt, g, p, q, m, k, l)-S(t, g, p, q, m, k, l) :5 :5, ' ', t :5 :5, '            ');
  end;
  d1 := t;
  WriteLn(t:5:5);

  d := d1;  g := g1;  p := p1;  q := q1;  m := m1;  k := k1;  l := l1;
end;
Function Sgrad(k : array of Extended) : Extended; {Сумма квадратов отклонений}
{var
  i : Word;
  Si : Extended;
begin
  Si := 0.0;
  for i := 0 to n do
    Si := Si + sqr(f(x0+dx*i, k[0], k[1], k[2], k[3], k[4], k[5], k[6])-y[i]);
  Sgrad := Si;
end;
Function norma(k : array of Extended) : Extended;
var
  i : Word;
  Si : Extended;
begin
  Si := 0;
  for i := 0 to 6 do Si := sqr(k[i]);
  norma := Si;
end;}
Procedure CalledKeyProc;FAR;
var
  kkf : ^Tkf;
  PPP : Pointer;
begin
  PPP := Pkf;
  kkf := PPP;
  x := x0; dx := (xn-x0)/1000;
  ymax := f(x0, kkf^[0],kkf^[1],kkf^[2],kkf^[3],kkf^[4],kkf^[5],kkf^[6]);
  ymin := f(xn, kkf^[0],kkf^[1],kkf^[2],kkf^[3],kkf^[4],kkf^[5],kkf^[6]);
  While x <= xn do
  begin
    PutPixel(20+Round((x-x0)/(xn-x0)*600),
                Yb-Round((f(x,kkf^[0],kkf^[1],kkf^[2],kkf^[3],kkf^[4],kkf^[5],kkf^[6])-ymin)/(ymax-ymin)*450.0),
                                 LightRed);
    x := x + dx;
  end;
{  SetColor(Yellow);
  Circle(100, 100, 100);}
end;
{Procedure KeyProc;FAR;Assembler;
asm
    pusha
    push ds
    push es

    in  al, 60h
    cmp al, 1
    jne @handler
    mov byte ptr hotkey, al

@handler:

    push offset @xfurther
    push cs
    jmp cs : dword ptr CalledKeyProc

@xfurther:

    in al, 61h
    push ax
    or  al, 80h
    out 61h, al
    pop ax
    out 61h, al

    mov al, 20h
    out 20h, al

    pop es
    pop ds
    popa
    iret
end;}
{Procedure ApprochGrad(var d, g, p, q, m, k, l : Extended);
var
  i : Word;
  t, dt : Extended;
  kf : array [0..6] of Extended;
  gradf : array [0..6] of Extended;
  Sg : Extended;
begin

  Pkf := @kf;
  kf[0]:=d;kf[1]:=g;kf[2]:=p;kf[3]:=q;
  kf[4]:=m;kf[5]:=k;kf[6]:=l;
{  asm
    push offset @further
    push cs
    jmp cs : dword ptr CalledKeyProc

@further:
  end;
    Exit;}
{  asm
    push es
    mov ax, 3509h
    int 21h
    mov word ptr oldint09h, bx
    mov word ptr oldint09h+2, es
    pop es
    push ds
    mov ax, seg KeyProc
    mov ds, ax
    mov dx, offset KeyProc
    mov ax, 2509h
    int 21h
    pop ds
  end;}
{  dt := 1.0E-8;

{  for i := 0 to 6 do kf[i] := 0;}
{  Repeat
   for i := 0 to 6 do
    begin
      kf[i] := kf[i]+dt;
      Sg := Sgrad(kf);
      kf[i] := kf[i]-dt;
      gradf[i] := (Sg-Sgrad(kf))/dt;
    end;
     Sg := norma(gradf);
   for i := 0 to 6 do
     begin
       if gradf[i]>0.0 then kf[i] := kf[i]-dt*(1000/Sg+1);
       if gradf[i]<0.0 then kf[i] := kf[i]+dt*(1000/Sg+1);
     end;
{     GotoXY(1, WhereY);
     Write(Sg:5:15);}
{     if HotKey then Break;}
{     if KeyPressed then if ReadKey=#27 then Break else CalledKeyProc;
   Until Sg < Eps;
  d := kf[0];  g := kf[1];  p := kf[2];  q := kf[3];  m := kf[4];  k := kf[5];  l := kf[6];
{  asm
    push ds
    mov ax, 2509h
    mov dx, word ptr oldint09h+2
    mov ds, dx
    mov dx, word ptr oldint09h
    pop ds
  end;}
{   While KeyPressed do ReadKey;
end;}

Function Max(Ar : array of Extended) : Extended;
var
  Mx : Word;
  j : Word;
begin
  Mx := 0;
  for j := 0 to n do
   if Ar[Mx]Ar[j] then Mn := j;
  Min := Ar[Mn];
end;

begin
{  WriteLn(Seg(ApprochGrad),':',Ofs(ApprochGrad));
  Halt;}
{  d := 0; g := 1.2; p := 0.002; q := -1.001; m := 0; k := -0.001; l := 0;
  d := 0;   g := 0;   p := 0;   q := 0;   m := 0;   k := 0;   l := 0;}
  ClrScr;
  dx := (xn-x0)/n;
  for i := 0 to n do
  y[i] := f(x0+dx*i, 0, 1.2, 0.002, -1.001, 0, -0.001, 0);
  ymax := Max(y);
  ymin := Min(y);
{  Approch(d, g, p, q, m, k, l);}
  Dr := Detect;        {Инициализируем графику}
  InitGraph(Dr, R, '');
  e :=  GraphResult;
  if e <> grOk then {Если ошибка}
  begin
    WriteLn('Ошибка инициализации графики!');
    WriteLn(GraphErrorMsg(e));
    ReadKey;
    Halt($FFFF);
  end;
  MoveTo(20, Yb-Round((y[0]-ymin)/(ymax-ymin)*450));
  SetColor(LightGreen);
  Circle(20, Yb-Round((y[0]-ymin)/(ymax-ymin)*450), 2);
  for i := 1 to n do
  begin
    SetColor(Yellow);
    LineTo(20+Round(i*dx/(xn-x0)*600), Yb-Round((y[i]-ymin)/(ymax-ymin)*450));
    SetColor(LightGreen);
    Circle(20+Round(i*dx/(xn-x0)*600), Yb-Round((y[i]-ymin)/(ymax-ymin)*450), 2);
  end;
  ApprochGrad(d, g, p, q, m, k, l);
  ReadKey;
  CloseGraph;
{  WriteLn(d:5:5, ' > ', g:5:5, ' > ', p:5:5, ' > ', q:5:5, ' > ', m:5:5, ' > ', k:5:5, ' > ', l:5:5);}
end.

Назад