00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00030
00031
00032
00033
00034 #ifdef __GNUG__
00035 #pragma implementation "Solver.h"
00036 #endif
00037
00038
00039 #include "mc/mcprec.h"
00040 #ifdef __BORLANDC__
00041 #pragma hdrstop
00042 #endif
00043
00044 #ifndef mcPRECOMP
00045 #include "mc/Solver.h"
00046 #include "mc/MathSystem.h"
00047 #include "mc/MathAndSystem.h"
00048 #include "mc/MathOrSystem.h"
00049 #include "mc/Symbol.h"
00050 #endif
00051
00052
00053
00054
00055
00056
00057
00058
00059 void mcSolver::math_ResetUnkArray()
00060 {
00061 for (int i=0; i < mcSOLVER_MAXLINES; i++)
00062 m_pUnkArr[i] = NULL;
00063 }
00064
00065 void mcSolver::math_SplitInTwoEquations(const mcPolynomial &lfirsteq, const mcPolynomial &rfirsteq,
00066 const mcPolynomial &lseceq, const mcPolynomial &rseceq,
00067 mcSystemStepArray &steps, mcLogicOperator conn)
00068 {
00069 mcMathLine *equ1 = new mcMathLine(lfirsteq, rfirsteq);
00070 mcMathLine *equ2 = new mcMathLine(lseceq, rseceq);
00071
00072
00073 math_SplitInTwoEquations(equ1, equ2, steps, conn);
00074 }
00075
00076
00077 void mcSolver::math_SplitInTwoEquations(const mcMathLine &equ1, const mcMathLine &equ2,
00078 mcSystemStepArray &steps, mcLogicOperator conn)
00079 {
00080
00081 math_SplitInTwoEquations(new mcMathLine(equ1), new mcMathLine(equ2), steps, conn);
00082 }
00083
00084 void mcSolver::math_SplitInTwoEquations(mcMathLine *equ1, mcMathLine *equ2,
00085 mcSystemStepArray &steps, mcLogicOperator conn)
00086 {
00087 mcMathOrSystem *step = new mcMathOrSystem();
00088
00089 if (conn == mcLO_OR) {
00090
00091
00092 step->data_AddLineToNewAndSystem(equ1);
00093 step->data_AddLineToNewAndSystem(equ2);
00094
00095 } else {
00096
00097
00098 step->data_AddLineToLastAndSystem(equ1);
00099 step->data_AddLineToLastAndSystem(equ2);
00100 }
00101
00102
00103 steps.data_Add(step);
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 #define mcDEFINE_EXPSIM_STEP(x, y) \
00138 void mcSolver::x(long flags, long rflags, mcMathLine &tosimp, \
00139 mcSystemStepArray &steps, \
00140 mcExpSimRes *result) { \
00141 \
00142 mcExpSimRes res = tosimp.y(flags, rflags); \
00143 if (result) *result = res; \
00144 steps.data_AddLine(tosimp); \
00145 }
00146
00147 #define mcDEFINE_EXPSIM_COMPLETE(x, y) \
00148 void mcSolver::x(long flags, long rflags, \
00149 mcMathLine &last, mcSystemStepArray &steps) { \
00150 mcExpSimRes res; \
00151 int cycles = 0; \
00152 \
00153 \
00154 y(flags, rflags, last, steps, &res); \
00155 mcSOLVERLOG(wxT("mcSolver::") wxT(#x) \
00156 wxT(" - completed 0-th step [%s]"), mcTXT(last)); \
00157 cycles++; \
00158 \
00159 \
00160 \
00161 \
00162 while (res != mcESR_DONE && \
00163 cycles < mcELEMENTMATH_MAX_PROCESS_CYCLES) { \
00164 \
00165 \
00166 y(flags, rflags, last, steps, &res); \
00167 mcSOLVERLOG(wxT("mcSolver::") wxT(#x) \
00168 wxT(" - completed %d-th step [%s]"), \
00169 cycles, mcTXT(last)); \
00170 cycles++; \
00171 } \
00172 }
00173
00174 mcDEFINE_EXPSIM_STEP(math_DoSimplifyStep, math_Simplify)
00175 mcDEFINE_EXPSIM_STEP(math_DoExpandStep, math_Expand)
00176 mcDEFINE_EXPSIM_COMPLETE(math_DoCompleteSimplification, math_DoSimplifyStep)
00177 mcDEFINE_EXPSIM_COMPLETE(math_DoCompleteExpansion, math_DoExpandStep)
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 void mcSolver::data_Check() const
00204 {
00205
00206 mcASSERT(!m_strName.IsEmpty(), wxT("Invalid name"));
00207 }
00208
00209 bool mcSolver::math_PreSolve(const mcMathOrSystem &p, mcSystemStepArray &steps)
00210 {
00211
00212 steps.data_AddSys(new mcMathOrSystem(p));
00213
00214
00215 for (int i=0; i < p.data_GetCount(); i++) {
00216 for (int k=0; k < p.data_GetSys(i).data_GetCount(); k++) {
00217
00218 const mcMathLine &line = p.data_GetSys(i).data_GetLine(k);
00219
00220
00221 for (int j=0; j < mcSymbol::arrUnknowns.data_GetCount(); j++) {
00222
00223 const mcSymbolProperties *sym = mcSymbol::arrUnknowns.data_GetSymbol(j);
00224 if (line.math_ContainsSymbol(sym)) {
00225
00226
00227 m_pUnkArr[i] = sym;
00228
00229
00230 if (math_WorksOn(p, sym))
00231 break;
00232 }
00233 }
00234
00235 if (m_pUnkArr[i] == NULL) {
00236
00237
00238 m_strLastErr = wxString::Format(wxT("The %d-th line [%s] does not contain")
00239 wxT("any unknown... cannot proceed"), i, mcTXT(line));
00240 return FALSE;
00241 }
00242
00243 mcMATHLOG(wxT("mcSolver::PreSolve - line %d will be solved for [%s]"),
00244 i, mcTXTP(m_pUnkArr[i]));
00245 }
00246 }
00247
00248 return TRUE;
00249 }
00250
00251 bool mcSolver::math_PostSolve(const mcMathOrSystem &p, mcSystemStepArray &steps)
00252 {
00253 mcMATHLOG(wxT("mcSolver::math_PostSolve - the step array is [%s]"), mcTXT(steps));
00254
00255
00256 int removed = steps.math_RemoveIdenticSteps();
00257
00258 #ifdef __MCDEBUG__
00259 mcMATHLOG(wxT("mcSolver::math_PostSolve - Removed %d useless steps."), removed);
00260 #else
00261 mcUNUSED(removed);
00262 #endif
00263
00264 return TRUE;
00265 }
00266
00267 bool mcSolver::math_Solve(const mcMathOrSystem &p, mcSystemStepArray &steps)
00268 {
00269
00270
00271
00272
00273 mcASSERT(math_isReady(), wxT("Cannot work yet"));
00274 mcASSERT(math_WorksOn(p), wxT("Invalid data for this type of solver"));
00275 mcMATHLOG(wxT("mcSolver::math_Solve - this solver is ready to work"));
00276
00277
00278 if (p.math_isConstant()) {
00279 m_strLastErr = wxT("The entire expression is constant; nothing to solve");
00280 return FALSE;
00281 }
00282
00283 if (!p.math_isValidMath()) {
00284 m_strLastErr = wxT("The expression contains invalid data");
00285 return FALSE;
00286 }
00287
00288
00289
00290 if (!math_PreSolve(p, steps))
00291 return FALSE;
00292
00293
00294 mcMATHLOG(wxT("mcSolver::math_Solve - the step array has %d steps"), steps.data_GetCount());
00295 for (int i=0; i < p.data_GetCount(); i++) {
00296 for (int j=0; j < p.data_GetSys(i).data_GetCount(); j++) {
00297
00298 mcMathLine tosolve(p.data_GetSys(i).data_GetLine(j));
00299 if (!math_SolveLine(tosolve, m_pUnkArr[i], steps))
00300 return FALSE;
00301
00302
00303 steps.math_RemoveSimpleSteps();
00304 steps.data_Check();
00305
00306 mcMATHLOG(wxT("mcSolver::math_Solve - the step array for the resolution ")
00307 wxT("of the %d-th line contains [%d] steps:\n%s"), i*j,
00308 steps.data_GetCount(), mcTXT(steps));
00309 }
00310 }
00311
00312
00313 return math_PostSolve(p, steps);
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 bool mcSolverArray::math_Add(mcSolver *solver)
00325 {
00326 if (math_Contains(solver))
00327 return FALSE;
00328
00329
00330 mcAbstractArray::data_Add(solver);
00331 return TRUE;
00332 }
00333
00334 wxArrayString mcSolverArray::io_GetDescArray() const
00335 {
00336 wxArrayString arr;
00337 for (int i=0; i < (int)data_GetCount(); i++)
00338 arr.Add(data_Get(i)->math_GetDesc());
00339 return arr;
00340 }
00341
00342 void mcSolverArray::data_Check() const
00343 {
00344 mcAbstractArray::data_Check();
00345 for (int i=0; i < data_GetCount(); i++)
00346 data_Get(i)->data_Check();
00347 }
00348
00349 bool mcSolverArray::math_Contains(const mcSolver *p) const
00350 {
00351 for (int i=0; i < data_GetCount(); i++)
00352 if (data_Get(i)->math_GetName() == p->math_GetName())
00353 return TRUE;
00354 return FALSE;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 void mcSystemStepArray::data_AddLine(const mcMathLine &p)
00376 {
00377
00378 if (m_nFlags & mcSYSTEMSTEPARR_DISCARD_SIMPLE) {
00379 data_AddLineOnlyIfComplexEnough(p);
00380 return;
00381 }
00382
00383 mcMathOrSystem *s=new mcMathOrSystem();
00384 s->data_AddLineToLastAndSystem(new mcMathLine(p));
00385
00386
00387 data_Add(s);
00388 }
00389
00390 void mcSystemStepArray::data_AddKeyLine(const mcMathLine &p)
00391 {
00392 mcMathOrSystem *s=new mcMathOrSystem();
00393 s->data_AddLineToLastAndSystem(new mcMathLine(p));
00394
00395
00396 data_Add(s);
00397 }
00398
00399 void mcSystemStepArray::data_AddSys(mcMathOrSystem *pointer)
00400 {
00401
00402 if (m_nFlags & mcSYSTEMSTEPARR_DISCARD_SIMPLE) {
00403 data_AddSysOnlyIfComplexEnough(pointer);
00404 return;
00405 }
00406
00407 mcAbstractArray::data_Add(pointer);
00408 }
00409
00410 void mcSystemStepArray::data_AddFinalSys(mcMathOrSystem *pointer)
00411 { mcAbstractArray::data_Add(pointer); }
00412
00413 void mcSystemStepArray::data_AddLineOnlyIfComplexEnough(const mcMathLine &p)
00414 {
00415 mcMathOrSystem *s=new mcMathOrSystem();
00416 s->data_AddLineToLastAndSystem(new mcMathLine(p));
00417
00418
00419 data_AddSysOnlyIfComplexEnough(s);
00420 }
00421
00422 void mcSystemStepArray::data_AddSysOnlyIfComplexEnough(mcMathOrSystem *p)
00423 {
00424 if (data_GetCount() < 1) {
00425 mcAbstractArray::data_Add(p);
00426 return;
00427 }
00428
00429 int i=data_GetCount()-1;
00430 mcRealValue last = data_Get(i)->math_GetTotalLenght();
00431 mcRealValue diff = p->math_GetTotalLenght()-last;
00432
00433
00434
00435 if (diff > mcMathCore::Get()->GetStepThreshold())
00436 mcAbstractArray::data_Add(p);
00437 else
00438 delete p;
00439 }
00440
00441 int mcSystemStepArray::math_RemoveIdenticSteps()
00442 {
00443 int removed = 0;
00444
00445
00446 for (int i=1; i < data_GetCount(); i++) {
00447
00448
00449
00450 if (data_Get(i)->math_Compare(*data_Get(i-1), FALSE)) {
00451
00452
00453
00454
00455 data_RemoveAt(i);
00456 removed++;
00457
00458
00459 i--;
00460 }
00461 }
00462
00463 return removed;
00464 }
00465
00466 int mcSystemStepArray::math_RemoveSimpleSteps()
00467 {
00468 int removed = 0;
00469
00470 if (data_GetCount() == 0) return 0;
00471 mcRealValue last = data_Get(0)->math_GetTotalLenght();
00472
00473
00474
00475 for (int i=1; i < data_GetCount()-1; i++) {
00476
00477
00478 mcRealValue currlenght = data_Get(i)->math_GetTotalLenght();
00479 mcRealValue diff = currlenght-last;
00480
00481 if (diff < mcMathCore::Get()->GetStepThreshold()) {
00482
00483
00484 data_RemoveAt(i);
00485 removed++;
00486
00487
00488 i--;
00489
00490 } else {
00491
00492 last = currlenght;
00493 }
00494
00495 data_Check();
00496 }
00497
00498 return removed;
00499 }
00500
00501 void mcSystemStepArray::data_Check() const
00502 {
00503 mcAbstractArray::data_Check();
00504 for (int i=0; i < data_GetCount(); i++)
00505 data_Get(i)->data_Check();
00506 }
00507
00508 void mcSystemStepArray::data_Delete(int n)
00509 {
00510
00511 delete data_Get(n);
00512 }
00513
00514 wxString mcSystemStepArray::io_GetInlinedExpr() const
00515 {
00516 wxString res;
00517
00518 for (int i=0; i < data_GetCount(); i++) {
00519
00520
00521 if (i>0) res+=wxT(" ");
00522 res += data_Get(i)->io_GetInlinedExpr();
00523 }
00524
00525 return res;
00526 }
00527
00528 void mcSystemStepArray::math_AppendCombinationOf(const mcSystemStepArray &arr1,
00529 const mcSystemStepArray &arr2,
00530 mcLogicOperator lo)
00531 {
00532 mcMATHLOG(wxT("mcSystemStepArray::math_AppendCombinationOf - merging\n\n%s\n\nwith\n\n%s"),
00533 mcTXT(arr1), mcTXT(arr2));
00534 int arr1idx=0, arr2idx=0;
00535
00536 for (int i=0,max=mcMAX(arr1.data_GetCount(), arr2.data_GetCount()); i<max; i++) {
00537
00538
00539
00540 mcMathOrSystem *toadd = new mcMathOrSystem();
00541 const mcMathOrSystem &first = *arr1.data_Get(arr1idx);
00542 const mcMathOrSystem &second = *arr2.data_Get(arr2idx);
00543
00544 switch (lo) {
00545 case mcLO_AND:
00546 toadd->math_AndMerge(first, second);
00547 break;
00548
00549 case mcLO_OR:
00550 toadd->math_OrMerge(first, second);
00551 break;
00552
00553 default:
00554 mcASSERT(0, wxT("Unhandled logical operator"));
00555 }
00556
00557
00558 data_Add(toadd);
00559
00560
00561 arr1idx++;
00562 arr2idx++;
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 if (arr1idx >= arr1.data_GetCount()) arr1idx = arr1.data_GetCount()-1;
00580 if (arr2idx >= arr2.data_GetCount()) arr2idx = arr2.data_GetCount()-1;
00581 }
00582 }
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634