@@ -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 ;
@@ -40,7 +39,6 @@ template <class T> class NashLcpBehaviorSolver {
4039
4140private:
4241 BehaviorCallbackType<T> m_onEquilibrium;
43- int m_stopAfter, m_maxDepth;
4442
4543 class Solution ;
4644
@@ -145,98 +143,23 @@ std::list<MixedBehaviorProfile<T>> NashLcpBehaviorSolver<T>::Solve(const Game &p
145143 solution.eps = tab.Epsilon ();
146144
147145 try {
148- if (m_stopAfter != 1 ) {
149- try {
150- AllLemke (p_game, solution.ns1 + solution.ns2 + 1 , tab, 0 , A, solution);
151- }
152- catch (EquilibriumLimitReached &) {
153- // Handle this silently; equilibria are recorded as found so no action needed
154- }
155- }
156- else {
157- tab.Pivot (solution.ns1 + solution.ns2 + 1 , 0 );
158- tab.SF_LCPPath (solution.ns1 + solution.ns2 + 1 );
159- solution.AddBFS (tab);
160- Vector<T> sol (tab.MinRow (), tab.MaxRow ());
161- tab.BasisVector (sol);
162- MixedBehaviorProfile<T> profile (p_game);
163- GetProfile (tab, profile, sol, p_game->GetRoot (), 1 , 1 , solution);
164- profile.UndefinedToCentroid ();
165- solution.m_equilibria .push_back (profile);
166- this ->m_onEquilibrium (profile, " NE" );
167- }
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" );
168156 }
169157 catch (std::runtime_error &e) {
170158 std::cerr << " Error: " << e.what () << std::endl;
171159 }
172160 return solution.m_equilibria ;
173161}
174162
175- //
176- // All_Lemke finds all accessible Nash equilibria by recursively
177- // calling itself. List maintains the list of basic variables
178- // for the equilibria that have already been found.
179- // From each new accessible equilibrium, it follows
180- // all possible paths, adding any new equilibria to the List.
181- //
182- template <class T >
183- void NashLcpBehaviorSolver<T>::AllLemke(const Game &p_game, int j, linalg::LemkeTableau<T> &B,
184- int depth, Matrix<T> &A, Solution &p_solution) const
185- {
186- if (m_maxDepth != 0 && depth > m_maxDepth) {
187- return ;
188- }
189-
190- Vector<T> sol (B.MinRow (), B.MaxRow ());
191- MixedBehaviorProfile<T> profile (p_game);
192-
193- bool newsol = false ;
194- for (int i = B.MinRow (); i <= B.MaxRow () && !newsol; i++) {
195- if (i == j) {
196- continue ;
197- }
198-
199- linalg::LemkeTableau<T> BCopy (B);
200- // Perturb tableau by a small number
201- A (i, 0 ) = static_cast <T>(-1 ) / static_cast <T>(1000 );
202- BCopy.Refactor ();
203-
204- int missing;
205- if (depth == 0 ) {
206- BCopy.Pivot (j, 0 );
207- missing = -j;
208- }
209- else {
210- missing = BCopy.SF_PivotIn (0 );
211- }
212-
213- newsol = false ;
214-
215- if (BCopy.SF_LCPPath (-missing) == 1 ) {
216- newsol = p_solution.AddBFS (BCopy);
217- BCopy.BasisVector (sol);
218- GetProfile (BCopy, profile, sol, p_game->GetRoot (), 1 , 1 , p_solution);
219- profile.UndefinedToCentroid ();
220- if (newsol) {
221- m_onEquilibrium (profile, " NE" );
222- p_solution.m_equilibria .push_back (profile);
223- if (m_stopAfter > 0 && p_solution.EquilibriumCount () >= m_stopAfter) {
224- throw EquilibriumLimitReached ();
225- }
226- }
227- }
228- else {
229- // Dead end
230- }
231-
232- A (i, 0 ) = static_cast <T>(-1 );
233- if (newsol) {
234- BCopy.Refactor ();
235- AllLemke (p_game, i, BCopy, depth + 1 , A, p_solution);
236- }
237- }
238- }
239-
240163template <class T >
241164void NashLcpBehaviorSolver<T>::FillTableau(Matrix<T> &A, const GameNode &n, T prob, int s1, int s2,
242165 T payoff1, T payoff2, Solution &p_solution) const
@@ -342,16 +265,15 @@ void NashLcpBehaviorSolver<T>::GetProfile(const linalg::LemkeTableau<T> &tab,
342265}
343266
344267template <class T >
345- std::list<MixedBehaviorProfile<T>> LcpBehaviorSolve (const Game &p_game, int p_stopAfter,
346- int p_maxDepth,
268+ std::list<MixedBehaviorProfile<T>> LcpBehaviorSolve (const Game &p_game,
347269 BehaviorCallbackType<T> p_onEquilibrium)
348270{
349- return NashLcpBehaviorSolver<T>(p_stopAfter, p_maxDepth, p_onEquilibrium).Solve (p_game);
271+ return NashLcpBehaviorSolver<T>(p_onEquilibrium).Solve (p_game);
350272}
351273
352- template std::list<MixedBehaviorProfile<double >> LcpBehaviorSolve (const Game &, int , int ,
274+ template std::list<MixedBehaviorProfile<double >> LcpBehaviorSolve (const Game &,
353275 BehaviorCallbackType<double >);
354276template std::list<MixedBehaviorProfile<Rational>>
355- LcpBehaviorSolve (const Game &, int , int , BehaviorCallbackType<Rational>);
277+ LcpBehaviorSolve (const Game &, BehaviorCallbackType<Rational>);
356278
357279} // end namespace Gambit::Nash
0 commit comments