@@ -29,9 +29,8 @@ namespace Gambit::Nash {
2929
3030template <class T > class NashLcpBehaviorSolver {
3131public:
32- NashLcpBehaviorSolver (int p_stopAfter, int p_maxDepth,
33- BehaviorCallbackType<T> p_onEquilibrium = NullBehaviorCallback<T>)
34- : m_onEquilibrium(p_onEquilibrium), m_stopAfter(p_stopAfter), m_maxDepth(p_maxDepth)
32+ NashLcpBehaviorSolver (BehaviorCallbackType<T> p_onEquilibrium = NullBehaviorCallback<T>)
33+ : m_onEquilibrium(p_onEquilibrium)
3534 {
3635 }
3736 ~NashLcpBehaviorSolver () = default ;
@@ -144,98 +143,23 @@ std::list<MixedBehaviorProfile<T>> NashLcpBehaviorSolver<T>::Solve(const Game &p
144143 solution.eps = tab.Epsilon ();
145144
146145 try {
147- if (m_stopAfter != 1 ) {
148- try {
149- AllLemke (p_game, solution.ns1 + solution.ns2 + 1 , tab, 0 , A, solution);
150- }
151- catch (EquilibriumLimitReached &) {
152- // Handle this silently; equilibria are recorded as found so no action needed
153- }
154- }
155- else {
156- tab.Pivot (solution.ns1 + solution.ns2 + 1 , 0 );
157- tab.SF_LCPPath (solution.ns1 + solution.ns2 + 1 );
158- solution.AddBFS (tab);
159- Vector<T> sol (tab.MinRow (), tab.MaxRow ());
160- tab.BasisVector (sol);
161- MixedBehaviorProfile<T> profile (p_game);
162- GetProfile (tab, profile, sol, p_game->GetRoot (), 1 , 1 , solution);
163- profile.UndefinedToCentroid ();
164- solution.m_equilibria .push_back (profile);
165- this ->m_onEquilibrium (profile, " NE" );
166- }
146+ tab.Pivot (solution.ns1 + solution.ns2 + 1 , 0 );
147+ tab.SF_LCPPath (solution.ns1 + solution.ns2 + 1 );
148+ solution.AddBFS (tab);
149+ Vector<T> sol (tab.MinRow (), tab.MaxRow ());
150+ tab.BasisVector (sol);
151+ MixedBehaviorProfile<T> profile (p_game);
152+ GetProfile (tab, profile, sol, p_game->GetRoot (), 1 , 1 , solution);
153+ profile.UndefinedToCentroid ();
154+ solution.m_equilibria .push_back (profile);
155+ this ->m_onEquilibrium (profile, " NE" );
167156 }
168157 catch (std::runtime_error &e) {
169158 std::cerr << " Error: " << e.what () << std::endl;
170159 }
171160 return solution.m_equilibria ;
172161}
173162
174- //
175- // All_Lemke finds all accessible Nash equilibria by recursively
176- // calling itself. List maintains the list of basic variables
177- // for the equilibria that have already been found.
178- // From each new accessible equilibrium, it follows
179- // all possible paths, adding any new equilibria to the List.
180- //
181- template <class T >
182- void NashLcpBehaviorSolver<T>::AllLemke(const Game &p_game, int j, linalg::LemkeTableau<T> &B,
183- int depth, Matrix<T> &A, Solution &p_solution) const
184- {
185- if (m_maxDepth != 0 && depth > m_maxDepth) {
186- return ;
187- }
188-
189- Vector<T> sol (B.MinRow (), B.MaxRow ());
190- MixedBehaviorProfile<T> profile (p_game);
191-
192- bool newsol = false ;
193- for (int i = B.MinRow (); i <= B.MaxRow () && !newsol; i++) {
194- if (i == j) {
195- continue ;
196- }
197-
198- linalg::LemkeTableau<T> BCopy (B);
199- // Perturb tableau by a small number
200- A (i, 0 ) = static_cast <T>(-1 ) / static_cast <T>(1000 );
201- BCopy.Refactor ();
202-
203- int missing;
204- if (depth == 0 ) {
205- BCopy.Pivot (j, 0 );
206- missing = -j;
207- }
208- else {
209- missing = BCopy.SF_PivotIn (0 );
210- }
211-
212- newsol = false ;
213-
214- if (BCopy.SF_LCPPath (-missing) == 1 ) {
215- newsol = p_solution.AddBFS (BCopy);
216- BCopy.BasisVector (sol);
217- GetProfile (BCopy, profile, sol, p_game->GetRoot (), 1 , 1 , p_solution);
218- profile.UndefinedToCentroid ();
219- if (newsol) {
220- m_onEquilibrium (profile, " NE" );
221- p_solution.m_equilibria .push_back (profile);
222- if (m_stopAfter > 0 && p_solution.EquilibriumCount () >= m_stopAfter) {
223- throw EquilibriumLimitReached ();
224- }
225- }
226- }
227- else {
228- // Dead end
229- }
230-
231- A (i, 0 ) = static_cast <T>(-1 );
232- if (newsol) {
233- BCopy.Refactor ();
234- AllLemke (p_game, i, BCopy, depth + 1 , A, p_solution);
235- }
236- }
237- }
238-
239163template <class T >
240164void NashLcpBehaviorSolver<T>::FillTableau(Matrix<T> &A, const GameNode &n, T prob, int s1, int s2,
241165 Solution &p_solution) const
@@ -341,16 +265,15 @@ void NashLcpBehaviorSolver<T>::GetProfile(const linalg::LemkeTableau<T> &tab,
341265}
342266
343267template <class T >
344- std::list<MixedBehaviorProfile<T>> LcpBehaviorSolve (const Game &p_game, int p_stopAfter,
345- int p_maxDepth,
268+ std::list<MixedBehaviorProfile<T>> LcpBehaviorSolve (const Game &p_game,
346269 BehaviorCallbackType<T> p_onEquilibrium)
347270{
348- return NashLcpBehaviorSolver<T>(p_stopAfter, p_maxDepth, p_onEquilibrium).Solve (p_game);
271+ return NashLcpBehaviorSolver<T>(p_onEquilibrium).Solve (p_game);
349272}
350273
351- template std::list<MixedBehaviorProfile<double >> LcpBehaviorSolve (const Game &, int , int ,
274+ template std::list<MixedBehaviorProfile<double >> LcpBehaviorSolve (const Game &,
352275 BehaviorCallbackType<double >);
353276template std::list<MixedBehaviorProfile<Rational>>
354- LcpBehaviorSolve (const Game &, int , int , BehaviorCallbackType<Rational>);
277+ LcpBehaviorSolve (const Game &, BehaviorCallbackType<Rational>);
355278
356279} // end namespace Gambit::Nash
0 commit comments