Statistiques
| Révision:

root / UFCalibrage.pas @ 3

Historique | Voir | Annoter | Télécharger (14,822 ko)

1
unit UFCalibrage;
2

    
3
interface
4

    
5
uses
6
  Windows, Forms, Classes, Controls, StdCtrls, Buttons, dmath;
7

    
8
type
9
  TFCalibrage = class(TForm)
10
    BBOk: TBitBtn;
11
    LTitle: TLabel;
12
    LMethod: TLabel;
13
    LTime: TLabel;
14
    ETime: TEdit;
15
    LPV: TLabel;
16
    LP2: TLabel;
17
    EPVRSD: TEdit;
18
    EP2RSD: TEdit;
19
    EPVR2: TEdit;
20
    LInitial: TLabel;
21
    LFinal: TLabel;
22
    ECoefEntGestInitial: TEdit;
23
    LStDev: TLabel;
24
    LCoefEntGest: TLabel;
25
    LCoefEntLact: TLabel;
26
    LRatioLipProt: TLabel;
27
    LInfo: TLabel;
28
    ECoefEntLactInitial: TEdit;
29
    ERatioLipProtInitial: TEdit;
30
    ECoefEntGestFinal: TEdit;
31
    ECoefEntLactFinal: TEdit;
32
    ERatioLipProtFinal: TEdit;
33
    ECoefEntGestStDev: TEdit;
34
    ECoefEntLactStDev: TEdit;
35
    ERatioLipProtStDev: TEdit;
36
    EMethod: TEdit;
37
    GBParam: TGroupBox;
38
    GBVariables: TGroupBox;
39
    EP2R2: TEdit;
40
    EPVVar: TEdit;
41
    EP2Var: TEdit;
42
    LR2: TLabel;
43
    LRSD: TLabel;
44
    LVar: TLabel;
45
    Lw: TLabel;
46
    EwP2: TEdit;
47
    EwPds: TEdit;
48
    procedure FormCreate(Sender: TObject);
49
    procedure FormDestroy(Sender: TObject);
50
    procedure FormShow(Sender: TObject);
51
  private
52
    { D?clarations priv?es }
53
    Pds, P2: TVector;
54
    X, G: TVector;
55
    H_inv: TMatrix;
56
    F_min, Det: Float;
57
    Freq, Start, Stop: Int64;
58
    MPds, MP2: Extended;
59
  public
60
    { D?clarations publiques }
61
  end;
62

    
63
var
64
  FCalibrage: TFCalibrage;
65

    
66
implementation
67

    
68
uses
69
  Graphics, Math, SysUtils, gnugettext, UVariables, UStrings, UFProfilT,
70
  UCalcSimulT;
71

    
72
{$R *.dfm}
73

    
74
{ Calibration }
75

    
76
const
77
  NVar = 3;
78
  NData = NB_CYCLES + NB_CYCLES - 1;
79
  MaxIter = 100;
80
  Tol = 1.0E-6;
81

    
82
var
83
  wPds, wP2: Extended;
84

    
85
function Func(X: TVector): Float;
86
var
87
  cycle, jour: Integer;
88
  GainProt: double;
89
  PdsSail, P2Sail, PdsMB, P2MB: array[1..NB_CYCLES] of double;
90
begin
91
  PProfilT.CoefEntretienGest := X[1];
92
  PProfilT.CoefEntretienLact := X[2];
93
  PProfilT.RatioLipProt := X[3];
94
  // calcul des CoefNR
95
  for cycle := 1 to NB_CYCLES do
96
    PProfilT.CoefNR[cycle] := 1;
97
  CalcSimulT(-1, -1, 1, 1, 8, 0, PResSimulT);
98
  GainProt := 0;
99
  for jour := 1 to PResSimulT.NbJSim do
100
    if PResSimulT.TabResult[3, jour] = 0
101
    then // Gestation
102
      GainProt := GainProt + PResSimulT.TabResult[63, jour]
103
    else
104
      if (PResSimulT.TabResult[3, jour] = 1) and (PResSimulT.TabResult[3, jour - 1] = 0)
105
      then // Mise bas
106
      begin
107
        cycle := Round(PResSimulT.TabResult[2, jour]);
108
        with PProfilT.Truies[cycle] do
109
          PProfilT.CoefNR[cycle] := Math.Max((0.178 * (PdsApMB - PdsSail) - 0.333 * (P2MB - P2Sail)) / (GainProt / 1000), 0);
110
        GainProt := 0;
111
      end;
112
  // ?valuation du cas
113
  CalcSimulT(-1, -1, 1, 1, 8, 0, PResSimulT);
114
  FProfilT.PBCoefEntGest.AsFloat := PProfilT.CoefEntretienGest;
115
  FProfilT.PBCoefEntLact.AsFloat := PProfilT.CoefEntretienLact;
116
  FProfilT.PBRatioLipProt.AsFloat := 1 - PProfilT.RatioLipProt;
117
  FProfilT.AffGraphCal;
118
  if FProfilT.GaugeCalibr.Progress < FProfilT.GaugeCalibr.MaxValue
119
  then
120
    FProfilT.GaugeCalibr.AddProgress(1)
121
  else
122
    FProfilT.GaugeCalibr.Progress := 1;
123
  Application.ProcessMessages;
124
  // poids et ?paisseur de lard apr?s gestation (mise bas)
125
  for jour := 2 to PResSimulT.NbJSim do
126
    if (PResSimulT.TabResult[3, jour] = 1) and (PResSimulT.TabResult[3, jour - 1] = 0)
127
    then
128
    begin
129
      cycle := Round(PResSimulT.TabResult[2, jour]);
130
      PdsMB[cycle] := PResSimulT.TabResult[60, jour - 1] + PResSimulT.TabResult[61, jour];
131
      P2MB[cycle] := PResSimulT.TabResult[67, jour - 1] + PResSimulT.TabResult[68, jour];
132
    end ;
133
  // poids et ?paisseur de lard apr?s lactation (saillie)
134
  for jour := 2 to PResSimulT.NbJSim do
135
    if (PResSimulT.TabResult[3, jour] = 0) and (PResSimulT.TabResult[3, jour - 1] = 2)
136
    then
137
      begin
138
        cycle := Round(PResSimulT.TabResult[2, jour]);
139
        PdsSail[cycle] := PResSimulT.TabResult[60, jour - 1] + PResSimulT.TabResult[61, jour];
140
        P2Sail[cycle] := PResSimulT.TabResult[67, jour - 1] + PResSimulT.TabResult[68, jour];
141
      end;
142
  // ?cart par rapport aux valeurs du profil
143
  Result := 0;
144
  for cycle := 1 to NB_CYCLES do
145
    Result := Result + Power(PdsMB[cycle] - PProfilT.Truies[cycle].PdsApMB, 2) * wPds;
146
  for cycle := 2 to NB_CYCLES do
147
    Result := Result + Power(PdsSail[cycle] - PProfilT.Truies[cycle].PdsSail, 2) * wPds;
148
  for cycle := 1 to NB_CYCLES do
149
    Result := Result + Power(P2MB[cycle] - PProfilT.Truies[cycle].P2MB, 2) * wP2;
150
  for cycle := 2 to NB_CYCLES do
151
    Result := Result + Power(P2Sail[cycle] - PProfilT.Truies[cycle].P2Sail, 2) * wP2;
152
end;
153

    
154
// Newton-Raphson method
155
// procedure HessGrad to compute the gradient G and the hessian H of the function at point X
156
{$I numhess.inc}
157

    
158
// Broyden-Fletcher-Goldfarb-Shanno method
159
// procedure Gradient to compute the gradient G of the function at point X
160
{$I numgrad.inc}
161

    
162
{ TFCalibrage }
163

    
164
procedure TFCalibrage.FormCreate(Sender: TObject);
165
var
166
  cycle: Integer;
167
  ETPds, ETP2: Extended;
168
begin
169
  if Screen.Fonts.IndexOf('Arial Unicode MS') <> -1
170
  then
171
    Font.Name := 'Arial Unicode MS';
172
  TranslateComponent(Self);
173
  // Initialisation des structures
174
  New(PResSimulT);
175
  DimVector(X, NVar);
176
  X[1] := PProfilT.CoefEntretienGest;
177
  X[2] := PProfilT.CoefEntretienLact;
178
  X[3] := PProfilT.RatioLipProt;
179
  DimVector(G, NVar);
180
  DimMatrix(H_inv, NVar, NVar);
181
  // Poids : moyenne et ?cart type
182
  DimVector(Pds, 2 * NB_CYCLES);
183
  for cycle := 2 to NB_CYCLES do
184
    Pds[cycle] := PProfilT.Truies[cycle].PdsSail;
185
  for cycle := 1 to NB_CYCLES do
186
    Pds[NB_CYCLES + cycle] := PProfilT.Truies[cycle].PdsApMB;
187
  MPds := dmath.Mean(Pds, 1, NData);
188
  ETPds := dmath.StDev(Pds, 1, NData, MPds);
189
  // Epaisseurs de lard : moyenne et ?cart type
190
  DimVector(P2, 2 * NB_CYCLES);
191
  for cycle := 2 to NB_CYCLES do
192
    P2[cycle] := PProfilT.Truies[cycle].P2Sail;
193
  for cycle := 1 to NB_CYCLES do
194
    P2[NB_CYCLES + cycle] := PProfilT.Truies[cycle].P2MB;
195
  MP2 := dmath.Mean(P2, 1, NData);
196
  ETP2 := dmath.StDev(P2, 1, NData, MP2);
197
  // Pond?rations
198
  wPds := 1 ;
199
  wP2 := Power(ETPds, 2) / Power(ETP2, 2);
200
//  wP2 := StrToFloat(InputBox('Question', 'Pond?ration relative', FloatToStrF(wP2, ffFixed, 15, 2)));
201
end;
202

    
203
procedure TFCalibrage.FormDestroy(Sender: TObject);
204
begin
205
  Dispose(PResSimulT);
206
end;
207

    
208
procedure TFCalibrage.FormShow(Sender: TObject);
209
var
210
  cycle, jour: Integer;
211
  PdsSail, P2Sail, PdsMB, P2MB: array[1..NB_CYCLES] of double;
212
  {MPds,} SStPds, SSrPds, {MP2,} SStP2, SSrP2: Float;
213
  {wM, wSStPds, wSSePds,} wSSrPds, {wSStP2, wSSeP2,} wSSrP2: Float;
214
begin
215
  ECoefEntGestInitial.Text := FProfilT.PBCoefEntGest.Text;
216
  ECoefEntLactInitial.Text := FProfilT.PBCoefEntLact.Text;
217
  ERatioLipProtInitial.Text := FProfilT.PBRatioLipProt.Text;
218
//  Screen.Cursor := crHourGlass;
219
  FProfilT.GaugeCalibr.Progress := 0;
220
  FProfilT.GaugeCalibr.Left := (FProfilT.GraphCalibr.Width - FProfilT.GaugeCalibr.Width) div 2;
221
  FProfilT.GaugeCalibr.Visible := True;
222
  Application.ProcessMessages;
223
  try
224
    if not QueryPerformanceFrequency(Freq) then Freq := 1;
225
    QueryPerformanceCounter(Start);
226
    case FProfilT.CBMethod.ItemIndex of
227
      0: Newton(Func, HessGrad, X, 1, NVar, MaxIter, Tol, F_min, G, H_inv, Det);
228
      1: Marquardt(Func, HessGrad, X, 1, NVar, MaxIter, Tol, F_min, G, H_inv, Det);
229
      2: BFGS(Func, Gradient, X, 1, NVar, MaxIter, Tol, F_min, G, H_inv);
230
    end;
231
  finally
232
    QueryPerformanceCounter(Stop);
233
//    Screen.Cursor:= crDefault;
234
    FProfilT.GaugeCalibr.Visible := False;
235
    Application.ProcessMessages;
236
  end;
237
  // Affichage du r?sultat obtenu
238
  PProfilT.CoefEntretienGest := X[1];
239
  PProfilT.CoefEntretienLact := X[2];
240
  PProfilT.RatioLipProt := X[3];
241
  CalcSimulT(-1, -1, 1, 1, 8, 0, PResSimulT);
242
  FProfilT.AffGraphCal ;
243
  FProfilT.PBCoefEntGest.AsFloat := PProfilT.CoefEntretienGest;
244
  FProfilT.PBCoefEntLact.AsFloat := PProfilT.CoefEntretienLact;
245
  FProfilT.PBRatioLipProt.AsFloat := 1 -PProfilT.RatioLipProt ;
246
  Application.ProcessMessages;
247
  EMethod.Text := FProfilT.CBMethod.Text;
248
  ETime.Text := FloatToStrF((Stop - Start) / Freq, ffFixed, 15, 3);
249
  ECoefEntGestFinal.Text := FProfilT.PBCoefEntGest.Text;
250
  if (FProfilT.PBCoefEntGest.AsFloat < FProfilT.PBCoefEntGest.MinValue)
251
  or (FProfilT.PBCoefEntGest.AsFloat > FProfilT.PBCoefEntGest.MaxValue)
252
  then
253
    ECoefEntGestFinal.Font.Color := clRed;
254
  ECoefEntLactFinal.Text := FProfilT.PBCoefEntLact.Text;
255
  if (FProfilT.PBCoefEntLact.AsFloat < FProfilT.PBCoefEntLact.MinValue)
256
  or (FProfilT.PBCoefEntLact.AsFloat > FProfilT.PBCoefEntLact.MaxValue)
257
  then
258
    ECoefEntLactFinal.Font.Color := clRed;
259
  ERatioLipProtFinal.Text := FProfilT.PBRatioLipProt.Text;
260
  if (FProfilT.PBRatioLipProt.AsFloat < FProfilT.PBRatioLipProt.MinValue)
261
  or (FProfilT.PBRatioLipProt.AsFloat > FProfilT.PBRatioLipProt.MaxValue)
262
  then
263
    ERatioLipProtFinal.Font.Color := clRed;
264
  // poids et ?paisseur de lard apr?s gestation (mise bas)
265
  for jour := 2 to PResSimulT.NbJSim do
266
    if (PResSimulT.TabResult[3, jour] = 1) and (PResSimulT.TabResult[3, jour - 1] = 0)
267
    then
268
    begin
269
      cycle := Round(PResSimulT.TabResult[2, jour]);
270
      PdsMB[cycle] := PResSimulT.TabResult[60, jour - 1] + PResSimulT.TabResult[61, jour];
271
      P2MB[cycle] := PResSimulT.TabResult[67, jour - 1] + PResSimulT.TabResult[68, jour];
272
    end ;
273
  // poids et ?paisseur de lard apr?s lactation (saillie)
274
  for jour := 2 to PResSimulT.NbJSim do
275
    if (PResSimulT.TabResult[3, jour] = 0) and (PResSimulT.TabResult[3, jour - 1] = 2)
276
    then
277
    begin
278
      cycle := Round(PResSimulT.TabResult[2, jour]);
279
      PdsSail[cycle] := PResSimulT.TabResult[60, jour - 1] + PResSimulT.TabResult[61, jour];
280
      P2Sail[cycle] := PResSimulT.TabResult[67, jour - 1] + PResSimulT.TabResult[68, jour];
281
    end;
282
{
283
  // Moyennes non pond?r?es
284
  MPds := 0;
285
  for cycle := 1 to NB_CYCLES do
286
    MPds := MPds + PProfilT.Truies[cycle].PdsApMB;
287
  for cycle := 2 to NB_CYCLES do
288
    MPds := MPds + PProfilT.Truies[cycle].PdsSail;
289
  MPds := MPds / NData;
290
  MP2 := 0;
291
  for cycle := 1 to NB_CYCLES do
292
    MP2 := MP2 + PProfilT.Truies[cycle].P2MB;
293
  for cycle := 2 to NB_CYCLES do
294
    MP2 := MP2 + PProfilT.Truies[cycle].P2Sail;
295
  MP2 := MP2 / NData;
296
}
297
  // Somme carr?e des ?carts totaux (non pond?r?s)
298
  SStPds := 0;
299
  for cycle := 1 to NB_CYCLES do
300
    SStPds := SStPds + Power(PProfilT.Truies[cycle].PdsApMB - MPds, 2);
301
  for cycle := 2 to NB_CYCLES do
302
    SStPds := SStPds + Power(PProfilT.Truies[cycle].PdsSail - MPds, 2);
303
  SStP2 := 0;
304
  for cycle := 1 to NB_CYCLES do
305
    SStP2 := SStP2 + Power(PProfilT.Truies[cycle].P2MB - MP2, 2);
306
  for cycle := 2 to NB_CYCLES do
307
    SStP2 := SStP2 + Power(PProfilT.Truies[cycle].P2Sail - MP2, 2);
308
  // Somme carr?e des ?carts des r?sidus (non pond?r?s)
309
  SSrPds := 0;
310
  for cycle := 1 to NB_CYCLES do
311
    SSrPds := SSrPds + Power(PProfilT.Truies[cycle].PdsApMB - PdsMB[cycle], 2);
312
  for cycle := 2 to NB_CYCLES do
313
    SSrPds := SSrPds + Power(PProfilT.Truies[cycle].PdsSail - PdsSail[cycle], 2);
314
  SSrP2 := 0;
315
  for cycle := 1 to NB_CYCLES do
316
    SSrP2 := SSrP2 + Power(PProfilT.Truies[cycle].P2MB - P2MB[cycle], 2);
317
  for cycle := 2 to NB_CYCLES do
318
    SSrP2 := SSrP2 + Power(PProfilT.Truies[cycle].P2Sail - P2Sail[cycle], 2);
319
 {
320
  // Moyenne pond?r?e
321
  wM := 0;
322
  for cycle := 1 to NB_CYCLES do
323
    wM := wM + PProfilT.Truies[cycle].PdsApMB * wPds;
324
  for cycle := 2 to NB_CYCLES do
325
    wM := wM + PProfilT.Truies[cycle].PdsSail * wPds;
326
  for cycle := 1 to NB_CYCLES do
327
    wM := wM + PProfilT.Truies[cycle].P2MB * wP2;
328
  for cycle := 2 to NB_CYCLES do
329
    wM := wM + PProfilT.Truies[cycle].P2Sail * wP2;
330
  wM := wM / (NData * wPds + NData * wP2);
331
  // Somme carr?e des ?carts totaux (pond?r?s)
332
  wSStPds := 0;
333
  for cycle := 1 to NB_CYCLES do
334
    wSStPds := wSStPds + Power(PProfilT.Truies[cycle].PdsApMB - wM, 2) * wPds;
335
  for cycle := 2 to NB_CYCLES do
336
    wSStPds := wSStPds + Power(PProfilT.Truies[cycle].PdsSail - wM, 2) * wPds;
337
  wSStP2 := 0;
338
  for cycle := 1 to NB_CYCLES do
339
    wSStP2 := wSStP2 + Power(PProfilT.Truies[cycle].P2MB - wM, 2) * wP2;
340
  for cycle := 2 to NB_CYCLES do
341
    wSStP2 := wSStP2 + Power(PProfilT.Truies[cycle].P2Sail - wM, 2) * wP2;
342
  // Somme carr?e des ?carts de pr?diction (pond?r?s)
343
  wSSePds := 0;
344
  for cycle := 1 to NB_CYCLES do
345
    wSSePds := wSSePds + Power(PdsMB[cycle] - wM, 2) * wPds;
346
  for cycle := 2 to NB_CYCLES do
347
    wSSePds := wSSePds + Power(PdsSail[cycle] - wM, 2) * wPds;
348
  wSSeP2 := 0;
349
  for cycle := 1 to NB_CYCLES do
350
    wSSeP2 := wSSeP2 + Power(P2MB[cycle] - wM, 2) * wP2;
351
  for cycle := 2 to NB_CYCLES do
352
    wSSeP2 := wSSeP2 + Power(P2Sail[cycle] - wM, 2) * wP2;
353
}
354
  // Somme carr?e des ?carts des r?sidus (pond?r?s)
355
  wSSrPds := 0;
356
  for cycle := 1 to NB_CYCLES do
357
    wSSrPds := wSSrPds + Power(PProfilT.Truies[cycle].PdsApMB - PdsMB[cycle], 2) * wPds;
358
  for cycle := 2 to NB_CYCLES do
359
    wSSrPds := wSSrPds + Power(PProfilT.Truies[cycle].PdsSail - PdsSail[cycle], 2) * wPds;
360
  wSSrP2 := 0;
361
  for cycle := 1 to NB_CYCLES do
362
    wSSrP2 := wSSrP2 + Power(PProfilT.Truies[cycle].P2MB - P2MB[cycle], 2) * wP2;
363
  for cycle := 2 to NB_CYCLES do
364
    wSSrP2 := wSSrP2 + Power(PProfilT.Truies[cycle].P2Sail - P2Sail[cycle], 2) * wP2;
365
  // Affichage des statistiques
366
  EwPds.Text := FloatToStrF(wPds, ffFixed, 15, 0);
367
  EwP2.Text := FloatToStrF(wP2, ffFixed, 15, 0);
368
  EPVRSD.Text := Format('%1.1f %s', [Sqrt(SSrPds / (NData - Nvar / 2)), StrKg]);
369
  EP2RSD.Text := Format('%1.2f %s', [Sqrt(SSrP2 / (NData - Nvar / 2)), StrMM]);
370
  EPVR2.Text := Format('%1.2f %%', [100 - SSrPds / SStPds * 100]);
371
  EP2R2.Text := Format('%1.2f %%', [100 - SSrP2 / SStP2 * 100]);
372
  EPVVar.Text := Format('%1.2f %%', [wSSrPds / (wSSrPds + wSSrP2) * 100]);
373
  EP2Var.Text := Format('%1.2f %%', [wSSrP2 / (wSSrPds + wSSrP2) * 100]);
374
  ECoefEntGestStDev.Text := FloatToStrF(Sqrt((wSSrPds + wSSrP2) / (2 * NData - Nvar) * H_inv[1, 1]), ffFixed, 15, 5);
375
  ECoefEntLactStDev.Text := FloatToStrF(Sqrt((wSSrPds + wSSrP2) / (2 * NData - Nvar) * H_inv[2, 2]), ffFixed, 15, 5);
376
  ERatioLipProtStDev.Text := FloatToStrF(Sqrt((wSSrPds + wSSrP2) / (2 * NData - Nvar) * H_inv[3, 3]), ffFixed, 15, 5);
377
  case MathErr of
378
    OptNonConv: LInfo.Caption := _('Non-convergence');
379
    OptSing: LInfo.Caption := _('Singular Hessian matrix');
380
    OptBigLambda: LInfo.Caption := _('Marquardt parameter too high');
381
    else
382
      if (FProfilT.PBCoefEntGest.AsFloat < FProfilT.PBCoefEntGest.MinValue)
383
      or (FProfilT.PBCoefEntGest.AsFloat > FProfilT.PBCoefEntGest.MaxValue)
384
      or (FProfilT.PBCoefEntLact.AsFloat < FProfilT.PBCoefEntLact.MinValue)
385
      or (FProfilT.PBCoefEntLact.AsFloat > FProfilT.PBCoefEntLact.MaxValue)
386
      or (FProfilT.PBRatioLipProt.AsFloat < FProfilT.PBRatioLipProt.MinValue)
387
      or (FProfilT.PBRatioLipProt.AsFloat > FProfilT.PBRatioLipProt.MaxValue)
388
      then
389
        LInfo.Caption := _('Suspicious result')
390
      else
391
        LInfo.Visible := False;
392
  end;
393
end;
394

    
395
end.