Skip to content

Commit ed213ab

Browse files
authored
Merge branch 'master' into dev_poly
2 parents bf6b113 + 1e75fea commit ed213ab

19 files changed

Lines changed: 2379 additions & 398 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,8 @@ Gambit.app/*
4343
*.so
4444
doc/tutorials/games/*.nfg
4545
doc/tutorials/games/*.efg
46+
doc/tutorials/*.png
4647
*.dmg
4748
Gambit.app/*
49+
*.ipynb_checkpoints
50+
*.ef

.readthedocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ build:
1212
apt_packages:
1313
- libgmp-dev
1414
- pandoc
15+
- texlive-full
1516

1617
python:
1718
install:

Makefile.am

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,11 @@ core_SOURCES = \
251251
src/core/recarray.h \
252252
src/core/matrix.h \
253253
src/core/matrix.imp \
254-
src/core/sqmatrix.h \
255-
src/core/sqmatrix.imp \
256254
src/core/integer.cc \
257255
src/core/integer.h \
258256
src/core/rational.cc \
259257
src/core/rational.h \
260258
src/core/matrix.cc \
261-
src/core/sqmatrix.cc \
262259
src/core/function.cc \
263260
src/core/function.h \
264261
src/core/tinyxml.cc \

doc/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ matplotlib
1010
pickleshare
1111
jupyter
1212
open_spiel; sys_platform != 'win32'
13+
draw-tree @ git+https://github.com/gambitproject/draw_tree.git@v0.2.0

doc/tutorials/02_extensive_form.ipynb

Lines changed: 966 additions & 40 deletions
Large diffs are not rendered by default.

doc/tutorials/03_stripped_down_poker.ipynb

Lines changed: 1243 additions & 81 deletions
Large diffs are not rendered by default.

src/core/matrix.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828

2929
namespace Gambit {
3030

31+
class SingularMatrixException final : public std::runtime_error {
32+
public:
33+
SingularMatrixException() : std::runtime_error("Attempted to invert a singular matrix") {}
34+
~SingularMatrixException() noexcept override = default;
35+
};
36+
3137
template <class T> Vector<T> operator*(const Vector<T> &, const Matrix<T> &);
3238

3339
template <class T> class Matrix : public RectArray<T> {
@@ -49,6 +55,10 @@ template <class T> class Matrix : public RectArray<T> {
4955

5056
/// @name Extracting rows and columns
5157
//@{
58+
bool IsSquare() const
59+
{
60+
return this->MinRow() == this->MinCol() && this->MaxRow() == this->MaxCol();
61+
}
5262
Vector<T> Row(int) const;
5363
Vector<T> Column(int) const;
5464
//@}
@@ -93,6 +103,9 @@ template <class T> class Matrix : public RectArray<T> {
93103
void MakeIdent();
94104
void Pivot(int, int);
95105
//@}
106+
107+
Matrix Inverse() const;
108+
T Determinant() const;
96109
};
97110

98111
template <class T> Vector<T> operator*(const Vector<T> &, const Matrix<T> &);

src/core/matrix.imp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ template <class T> Vector<T> Matrix<T>::Column(int j) const
384384

385385
template <class T> void Matrix<T>::MakeIdent()
386386
{
387+
if (!IsSquare()) {
388+
throw DimensionException();
389+
}
387390
for (int i = this->minrow; i <= this->maxrow; i++) {
388391
for (int j = this->mincol; j <= this->maxcol; j++) {
389392
if (i == j) {
@@ -426,4 +429,139 @@ template <class T> void Matrix<T>::Pivot(int row, int col)
426429
}
427430
}
428431

432+
template <class T> Matrix<T> Matrix<T>::Inverse() const
433+
{
434+
if (!IsSquare()) {
435+
throw DimensionException();
436+
}
437+
438+
Matrix copy(*this);
439+
Matrix inv(this->MaxRow(), this->MaxRow());
440+
441+
// initialize inverse matrix and prescale row vectors
442+
for (int i = this->MinRow(); i <= this->MaxRow(); i++) {
443+
T max = (T)0;
444+
for (int j = this->MinCol(); j <= this->MaxCol(); j++) {
445+
T abs = copy(i, j);
446+
if (abs < (T)0) {
447+
abs = -abs;
448+
}
449+
if (abs > max) {
450+
max = abs;
451+
}
452+
}
453+
454+
if (max == (T)0) {
455+
throw SingularMatrixException();
456+
}
457+
458+
T scale = (T)1 / max;
459+
for (int j = this->MinCol(); j <= this->MaxCol(); j++) {
460+
copy(i, j) *= scale;
461+
if (i == j) {
462+
inv(i, j) = scale;
463+
}
464+
else {
465+
inv(i, j) = (T)0;
466+
}
467+
}
468+
}
469+
470+
for (int i = this->MinCol(); i <= this->MaxCol(); i++) {
471+
// find pivot row
472+
T max = copy(i, i);
473+
if (max < (T)0) {
474+
max = -max;
475+
}
476+
int row = i;
477+
for (int j = i + 1; j <= this->MaxRow(); j++) {
478+
T abs = copy(j, i);
479+
if (abs < (T)0) {
480+
abs = -abs;
481+
}
482+
if (abs > max) {
483+
max = abs;
484+
row = j;
485+
}
486+
}
487+
488+
if (max <= (T)0) {
489+
throw SingularMatrixException();
490+
}
491+
492+
copy.SwitchRows(i, row);
493+
inv.SwitchRows(i, row);
494+
// scale pivot row
495+
T factor = (T)1 / copy(i, i);
496+
for (int k = this->MinCol(); k <= this->MaxCol(); k++) {
497+
copy(i, k) *= factor;
498+
inv(i, k) *= factor;
499+
}
500+
501+
// reduce other rows
502+
for (int j = this->MinRow(); j <= this->MaxRow(); j++) {
503+
if (j != i) {
504+
T mult = copy(j, i);
505+
for (int k = this->MinCol(); k <= this->MaxCol(); k++) {
506+
copy(j, k) -= copy(i, k) * mult;
507+
inv(j, k) -= inv(i, k) * mult;
508+
}
509+
}
510+
}
511+
}
512+
513+
return inv;
514+
}
515+
516+
template <class T> T Matrix<T>::Determinant() const
517+
{
518+
if (!IsSquare()) {
519+
throw DimensionException();
520+
}
521+
522+
T factor = (T)1;
523+
Matrix M(*this);
524+
525+
for (int row = this->MinRow(); row <= this->MaxRow(); row++) {
526+
527+
// Experience (as of 3/22/99) suggests that, in the interest of
528+
// numerical stability, it might be best to do Gaussian
529+
// elimination with respect to the row (of those feasible)
530+
// whose entry has the largest absolute value.
531+
int swap_row = row;
532+
for (int i = row + 1; i <= this->MaxRow(); i++) {
533+
if (abs(M.data[i][row]) > abs(M.data[swap_row][row])) {
534+
swap_row = i;
535+
}
536+
}
537+
538+
if (swap_row != row) {
539+
M.SwitchRows(row, swap_row);
540+
for (int j = this->MinCol(); j <= this->MaxCol(); j++) {
541+
M.data[row][j] *= (T)-1;
542+
}
543+
}
544+
545+
if (M.data[row][row] == (T)0) {
546+
return (T)0;
547+
}
548+
549+
// now do row operations to clear the row'th column
550+
// below the diagonal
551+
for (int row1 = row + 1; row1 <= this->MaxRow(); row1++) {
552+
factor = -M.data[row1][row] / M.data[row][row];
553+
for (int i = this->MinCol(); i <= this->MaxCol(); i++) {
554+
M.data[row1][i] += M.data[row][i] * factor;
555+
}
556+
}
557+
}
558+
559+
// finally we multiply the diagonal elements
560+
T det = (T)1;
561+
for (int row = this->MinRow(); row <= this->MaxRow(); row++) {
562+
det *= M.data[row][row];
563+
}
564+
return det;
565+
}
566+
429567
} // end namespace Gambit

src/core/sqmatrix.cc

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/core/sqmatrix.h

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)