7
7
import numpy as np
8
8
from numba import jit
9
9
from .utilities import NashResult
10
-
11
-
12
- TOL_PIV = 1e-10
13
- TOL_RATIO_DIFF = 1e-15
10
+ from ..optimize .pivoting import _pivoting , _lex_min_ratio_test
14
11
15
12
16
13
def lemke_howson (g , init_pivot = 0 , max_iter = 10 ** 6 , capping = None ,
@@ -398,8 +395,8 @@ def _lemke_howson_tbl(tableaux, bases, init_pivot, max_iter):
398
395
while True :
399
396
for pl in pls :
400
397
# Determine the leaving variable
401
- row_min = _lex_min_ratio_test (tableaux [pl ], pivot ,
402
- slack_starts [pl ], argmins )
398
+ _ , row_min = _lex_min_ratio_test (tableaux [pl ], pivot ,
399
+ slack_starts [pl ], argmins )
403
400
404
401
# Pivoting step: modify tableau in place
405
402
_pivoting (tableaux [pl ], pivot , row_min )
@@ -421,147 +418,6 @@ def _lemke_howson_tbl(tableaux, bases, init_pivot, max_iter):
421
418
return converged , num_iter
422
419
423
420
424
- @jit (nopython = True , cache = True )
425
- def _pivoting (tableau , pivot , pivot_row ):
426
- """
427
- Perform a pivoting step. Modify `tableau` in place.
428
-
429
- Parameters
430
- ----------
431
- tableau : ndarray(float, ndim=2)
432
- Array containing the tableau.
433
-
434
- pivot : scalar(int)
435
- Pivot.
436
-
437
- pivot_row : scalar(int)
438
- Pivot row index.
439
-
440
- Returns
441
- -------
442
- tableau : ndarray(float, ndim=2)
443
- View to `tableau`.
444
-
445
- """
446
- nrows , ncols = tableau .shape
447
-
448
- pivot_elt = tableau [pivot_row , pivot ]
449
- for j in range (ncols ):
450
- tableau [pivot_row , j ] /= pivot_elt
451
-
452
- for i in range (nrows ):
453
- if i == pivot_row :
454
- continue
455
- multiplier = tableau [i , pivot ]
456
- if multiplier == 0 :
457
- continue
458
- for j in range (ncols ):
459
- tableau [i , j ] -= tableau [pivot_row , j ] * multiplier
460
-
461
- return tableau
462
-
463
-
464
- @jit (nopython = True , cache = True )
465
- def _min_ratio_test_no_tie_breaking (tableau , pivot , test_col ,
466
- argmins , num_candidates ):
467
- """
468
- Perform the minimum ratio test, without tie breaking, for the
469
- candidate rows in `argmins[:num_candidates]`. Return the number
470
- `num_argmins` of the rows minimizing the ratio and store thier
471
- indices in `argmins[:num_argmins]`.
472
-
473
- Parameters
474
- ----------
475
- tableau : ndarray(float, ndim=2)
476
- Array containing the tableau.
477
-
478
- pivot : scalar(int)
479
- Pivot.
480
-
481
- test_col : scalar(int)
482
- Index of the column used in the test.
483
-
484
- argmins : ndarray(int, ndim=1)
485
- Array containing the indices of the candidate rows. Modified in
486
- place to store the indices of minimizing rows.
487
-
488
- num_candidates : scalar(int)
489
- Number of candidate rows in `argmins`.
490
-
491
- Returns
492
- -------
493
- num_argmins : scalar(int)
494
- Number of minimizing rows.
495
-
496
- """
497
- ratio_min = np .inf
498
- num_argmins = 0
499
-
500
- for k in range (num_candidates ):
501
- i = argmins [k ]
502
- if tableau [i , pivot ] <= TOL_PIV : # Treated as nonpositive
503
- continue
504
- ratio = tableau [i , test_col ] / tableau [i , pivot ]
505
- if ratio > ratio_min + TOL_RATIO_DIFF : # Ratio large for i
506
- continue
507
- elif ratio < ratio_min - TOL_RATIO_DIFF : # Ratio smaller for i
508
- ratio_min = ratio
509
- num_argmins = 1
510
- else : # Ratio equal
511
- num_argmins += 1
512
- argmins [num_argmins - 1 ] = i
513
-
514
- return num_argmins
515
-
516
-
517
- @jit (nopython = True , cache = True )
518
- def _lex_min_ratio_test (tableau , pivot , slack_start , argmins ):
519
- """
520
- Perform the lexico-minimum ratio test.
521
-
522
- Parameters
523
- ----------
524
- tableau : ndarray(float, ndim=2)
525
- Array containing the tableau.
526
-
527
- pivot : scalar(int)
528
- Pivot.
529
-
530
- slack_start : scalar(int)
531
- First index for the slack variables.
532
-
533
- argmins : ndarray(int, ndim=1)
534
- Empty array used to store the row indices. Its length must be no
535
- smaller than the number of the rows of `tableau`.
536
-
537
- Returns
538
- -------
539
- row_min : scalar(int)
540
- Index of the row with the lexico-minimum ratio.
541
-
542
- """
543
- nrows = tableau .shape [0 ]
544
- num_candidates = nrows
545
-
546
- # Initialize `argmins`
547
- for i in range (nrows ):
548
- argmins [i ] = i
549
-
550
- num_argmins = _min_ratio_test_no_tie_breaking (tableau , pivot , - 1 ,
551
- argmins , num_candidates )
552
- if num_argmins == 1 :
553
- return argmins [0 ]
554
-
555
- for j in range (slack_start , slack_start + nrows ):
556
- if j == pivot :
557
- continue
558
- num_argmins = _min_ratio_test_no_tie_breaking (tableau , pivot , j ,
559
- argmins , num_argmins )
560
- if num_argmins == 1 :
561
- break
562
- return argmins [0 ]
563
-
564
-
565
421
@jit (nopython = True , cache = True )
566
422
def _get_mixed_actions (tableaux , bases ):
567
423
"""
0 commit comments