77import numpy as np
88from numba import jit
99from .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
1411
1512
1613def 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):
398395 while True :
399396 for pl in pls :
400397 # 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 )
403400
404401 # Pivoting step: modify tableau in place
405402 _pivoting (tableaux [pl ], pivot , row_min )
@@ -421,147 +418,6 @@ def _lemke_howson_tbl(tableaux, bases, init_pivot, max_iter):
421418 return converged , num_iter
422419
423420
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-
565421@jit (nopython = True , cache = True )
566422def _get_mixed_actions (tableaux , bases ):
567423 """
0 commit comments