Skip to content

Commit

Permalink
Refactor polynomial-related classes formerly in prepoly.h
Browse files Browse the repository at this point in the history
This reorganises and simplifies some of the preliminary classes
underlying the implementation of multivariate polynomials:

* Ordering of exponent vectors is now a property of vectors (or more properly the space)
  and not a separate concept
* Functions inlined - most of the operations in these classes are simple and suitable for inlining
* Rationalised and standardised namings of the concepts
* Moved to gpoly.h so the polynomial implementation is now self-contained.
  • Loading branch information
tturocy committed Dec 13, 2024
1 parent 9cfe468 commit 15b956e
Show file tree
Hide file tree
Showing 20 changed files with 326 additions and 2,654 deletions.
8 changes: 0 additions & 8 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,6 @@ gambit_enumpoly_SOURCES = \
src/solvers/enumpoly/ineqsolv.h \
src/solvers/enumpoly/ineqsolv.imp \
src/solvers/enumpoly/interval.h \
src/solvers/enumpoly/monomial.cc \
src/solvers/enumpoly/monomial.h \
src/solvers/enumpoly/monomial.imp \
src/solvers/enumpoly/poly.cc \
src/solvers/enumpoly/poly.h \
src/solvers/enumpoly/poly.imp \
src/solvers/enumpoly/prepoly.cc \
src/solvers/enumpoly/prepoly.h \
src/solvers/enumpoly/quiksolv.cc \
src/solvers/enumpoly/quiksolv.h \
src/solvers/enumpoly/quiksolv.imp \
Expand Down
87 changes: 41 additions & 46 deletions src/solvers/enumpoly/behavextend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,19 @@ List<GameInfoset> DeviationInfosets(const BehaviorSupportProfile &big_supp, cons
}

gPolyList<double> ActionProbsSumToOneIneqs(const MixedBehaviorProfile<double> &p_solution,
const gSpace &BehavStratSpace, const term_order &Lex,
const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &big_supp,
const std::map<GameInfoset, int> &var_index)
{
gPolyList<double> answer(&BehavStratSpace, &Lex);
gPolyList<double> answer(&BehavStratSpace);

for (auto player : p_solution.GetGame()->GetPlayers()) {
for (auto infoset : player->GetInfosets()) {
if (!big_supp.HasAction(infoset)) {
int index_base = var_index.at(infoset);
gPoly<double> factor(&BehavStratSpace, 1.0, &Lex);
gPoly<double> factor(&BehavStratSpace, 1.0);
for (int k = 1; k < infoset->NumActions(); k++) {
factor -= gPoly<double>(&BehavStratSpace, index_base + k, 1, &Lex);
factor -= gPoly<double>(&BehavStratSpace, index_base + k, 1);
}
answer += factor;
}
Expand Down Expand Up @@ -177,8 +177,8 @@ std::list<BehaviorSupportProfile> DeviationSupports(const BehaviorSupportProfile
}

bool NashNodeProbabilityPoly(const MixedBehaviorProfile<double> &p_solution,
gPoly<double> &node_prob, const gSpace &BehavStratSpace,
const term_order &Lex, const BehaviorSupportProfile &dsupp,
gPoly<double> &node_prob, const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &dsupp,
const std::map<GameInfoset, int> &var_index, GameNode tempnode,
const GameInfoset &iset, const GameAction &act)
{
Expand Down Expand Up @@ -209,12 +209,12 @@ bool NashNodeProbabilityPoly(const MixedBehaviorProfile<double> &p_solution,
int initial_var_no = var_index.at(last_infoset);
if (last_action->GetNumber() < last_infoset->NumActions()) {
int varno = initial_var_no + last_action->GetNumber();
node_prob *= gPoly<double>(&BehavStratSpace, varno, 1, &Lex);
node_prob *= gPoly<double>(&BehavStratSpace, varno, 1);
}
else {
gPoly<double> factor(&BehavStratSpace, 1.0, &Lex);
gPoly<double> factor(&BehavStratSpace, 1.0);
for (int k = 1; k < last_infoset->NumActions(); k++) {
factor -= gPoly<double>(&BehavStratSpace, initial_var_no + k, 1, &Lex);
factor -= gPoly<double>(&BehavStratSpace, initial_var_no + k, 1);
}
node_prob *= factor;
}
Expand All @@ -225,12 +225,12 @@ bool NashNodeProbabilityPoly(const MixedBehaviorProfile<double> &p_solution,
}

gPolyList<double> NashExpectedPayoffDiffPolys(const MixedBehaviorProfile<double> &p_solution,
const gSpace &BehavStratSpace, const term_order &Lex,
const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &little_supp,
const BehaviorSupportProfile &big_supp,
const std::map<GameInfoset, int> &var_index)
{
gPolyList<double> answer(&BehavStratSpace, &Lex);
gPolyList<double> answer(&BehavStratSpace);

auto terminal_nodes = TerminalNodes(p_solution.GetGame());

Expand All @@ -249,12 +249,12 @@ gPolyList<double> NashExpectedPayoffDiffPolys(const MixedBehaviorProfile<double>
// The utility difference between the
// payoff resulting from the profile and deviation to
// the strategy for pl specified by dsupp[k]
gPoly<double> next_poly(&BehavStratSpace, &Lex);
gPoly<double> next_poly(&BehavStratSpace);

for (auto node : terminal_nodes) {
gPoly<double> node_prob(&BehavStratSpace, 1.0, &Lex);
if (NashNodeProbabilityPoly(p_solution, node_prob, BehavStratSpace, Lex, support,
var_index, node, infoset, action)) {
gPoly<double> node_prob(&BehavStratSpace, 1.0);
if (NashNodeProbabilityPoly(p_solution, node_prob, BehavStratSpace, support, var_index,
node, infoset, action)) {
if (node->GetOutcome()) {
node_prob *= static_cast<double>(node->GetOutcome()->GetPayoff(player));
}
Expand All @@ -270,15 +270,15 @@ gPolyList<double> NashExpectedPayoffDiffPolys(const MixedBehaviorProfile<double>
}

gPolyList<double> ExtendsToNashIneqs(const MixedBehaviorProfile<double> &p_solution,
const gSpace &BehavStratSpace, const term_order &Lex,
const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &little_supp,
const BehaviorSupportProfile &big_supp,
const std::map<GameInfoset, int> &var_index)
{
gPolyList<double> answer(&BehavStratSpace, &Lex);
answer += ActionProbsSumToOneIneqs(p_solution, BehavStratSpace, Lex, big_supp, var_index);
answer += NashExpectedPayoffDiffPolys(p_solution, BehavStratSpace, Lex, little_supp, big_supp,
var_index);
gPolyList<double> answer(&BehavStratSpace);
answer += ActionProbsSumToOneIneqs(p_solution, BehavStratSpace, big_supp, var_index);
answer +=
NashExpectedPayoffDiffPolys(p_solution, BehavStratSpace, little_supp, big_supp, var_index);
return answer;
}

Expand Down Expand Up @@ -306,12 +306,10 @@ bool ExtendsToNash(const MixedBehaviorProfile<double> &p_solution,
}

// We establish the space
gSpace BehavStratSpace(num_vars);
ORD_PTR ptr = &lex;
term_order Lex(&BehavStratSpace, ptr);
VariableSpace BehavStratSpace(num_vars);

gPolyList<double> inequalities =
ExtendsToNashIneqs(p_solution, BehavStratSpace, Lex, little_supp, big_supp, var_index);
ExtendsToNashIneqs(p_solution, BehavStratSpace, little_supp, big_supp, var_index);
// set up the rectangle of search
Vector<double> bottoms(num_vars), tops(num_vars);
bottoms = 0;
Expand All @@ -328,8 +326,8 @@ bool ExtendsToNash(const MixedBehaviorProfile<double> &p_solution,
namespace {

bool ANFNodeProbabilityPoly(const MixedBehaviorProfile<double> &p_solution,
gPoly<double> &node_prob, const gSpace &BehavStratSpace,
const term_order &Lex, const BehaviorSupportProfile &big_supp,
gPoly<double> &node_prob, const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &big_supp,
const std::map<GameInfoset, int> &var_index, GameNode tempnode, int pl,
int i, int j)
{
Expand Down Expand Up @@ -357,12 +355,12 @@ bool ANFNodeProbabilityPoly(const MixedBehaviorProfile<double> &p_solution,
int initial_var_no = var_index.at(last_infoset);
if (last_action->GetNumber() < last_infoset->NumActions()) {
int varno = initial_var_no + last_action->GetNumber();
node_prob *= gPoly<double>(&BehavStratSpace, varno, 1, &Lex);
node_prob *= gPoly<double>(&BehavStratSpace, varno, 1);
}
else {
gPoly<double> factor(&BehavStratSpace, 1.0, &Lex);
gPoly<double> factor(&BehavStratSpace, 1.0);
for (int k = 1; k < last_infoset->NumActions(); k++) {
factor -= gPoly<double>(&BehavStratSpace, initial_var_no + k, 1, &Lex);
factor -= gPoly<double>(&BehavStratSpace, initial_var_no + k, 1);
}
node_prob *= factor;
}
Expand All @@ -373,12 +371,12 @@ bool ANFNodeProbabilityPoly(const MixedBehaviorProfile<double> &p_solution,
}

gPolyList<double> ANFExpectedPayoffDiffPolys(const MixedBehaviorProfile<double> &p_solution,
const gSpace &BehavStratSpace, const term_order &Lex,
const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &little_supp,
const BehaviorSupportProfile &big_supp,
const std::map<GameInfoset, int> &var_index)
{
gPolyList<double> answer(&BehavStratSpace, &Lex);
gPolyList<double> answer(&BehavStratSpace);

auto terminal_nodes = TerminalNodes(p_solution.GetGame());

Expand All @@ -394,12 +392,12 @@ gPolyList<double> ANFExpectedPayoffDiffPolys(const MixedBehaviorProfile<double>
// This will be the utility difference between the
// payoff resulting from the profile and deviation to
// action j
gPoly<double> next_poly(&BehavStratSpace, &Lex);
gPoly<double> next_poly(&BehavStratSpace);
for (auto terminal : terminal_nodes) {
gPoly<double> node_prob(&BehavStratSpace, 1.0, &Lex);
if (ANFNodeProbabilityPoly(p_solution, node_prob, BehavStratSpace, Lex, big_supp,
var_index, terminal, player->GetNumber(),
infoset->GetNumber(), action->GetNumber())) {
gPoly<double> node_prob(&BehavStratSpace, 1.0);
if (ANFNodeProbabilityPoly(p_solution, node_prob, BehavStratSpace, big_supp, var_index,
terminal, player->GetNumber(), infoset->GetNumber(),
action->GetNumber())) {
if (terminal->GetOutcome()) {
node_prob *= static_cast<double>(terminal->GetOutcome()->GetPayoff(player));
}
Expand All @@ -414,15 +412,15 @@ gPolyList<double> ANFExpectedPayoffDiffPolys(const MixedBehaviorProfile<double>
}

gPolyList<double> ExtendsToANFNashIneqs(const MixedBehaviorProfile<double> &p_solution,
const gSpace &BehavStratSpace, const term_order &Lex,
const VariableSpace &BehavStratSpace,
const BehaviorSupportProfile &little_supp,
const BehaviorSupportProfile &big_supp,
const std::map<GameInfoset, int> &var_index)
{
gPolyList<double> answer(&BehavStratSpace, &Lex);
answer += ActionProbsSumToOneIneqs(p_solution, BehavStratSpace, Lex, big_supp, var_index);
answer += ANFExpectedPayoffDiffPolys(p_solution, BehavStratSpace, Lex, little_supp, big_supp,
var_index);
gPolyList<double> answer(&BehavStratSpace);
answer += ActionProbsSumToOneIneqs(p_solution, BehavStratSpace, big_supp, var_index);
answer +=
ANFExpectedPayoffDiffPolys(p_solution, BehavStratSpace, little_supp, big_supp, var_index);
return answer;
}

Expand All @@ -448,13 +446,10 @@ bool ExtendsToAgentNash(const MixedBehaviorProfile<double> &p_solution,
}

// We establish the space
gSpace BehavStratSpace(num_vars);
ORD_PTR ptr = &lex;
term_order Lex(&BehavStratSpace, ptr);

VariableSpace BehavStratSpace(num_vars);
num_vars = BehavStratSpace.Dmnsn();
gPolyList<double> inequalities =
ExtendsToANFNashIneqs(p_solution, BehavStratSpace, Lex, little_supp, big_supp, var_index);
ExtendsToANFNashIneqs(p_solution, BehavStratSpace, little_supp, big_supp, var_index);

// set up the rectangle of search
Vector<double> bottoms(num_vars), tops(num_vars);
Expand Down
18 changes: 8 additions & 10 deletions src/solvers/enumpoly/efgpoly.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ namespace {
class ProblemData {
public:
GameSequenceForm sfg;
gSpace Space;
term_order Lex;
VariableSpace Space;
std::map<GameSequence, int> var;
std::map<GameSequence, gPoly<double>> variables;

Expand All @@ -65,13 +64,13 @@ gPoly<double> BuildSequenceVariable(ProblemData &p_data, const GameSequence &p_s
const std::map<GameSequence, int> &var)
{
if (!p_sequence->action) {
return {&p_data.Space, 1, &p_data.Lex};
return {&p_data.Space, 1};
}
if (p_sequence->action != p_data.sfg.GetSupport().GetActions(p_sequence->GetInfoset()).back()) {
return {&p_data.Space, var.at(p_sequence), 1, &p_data.Lex};
return {&p_data.Space, var.at(p_sequence), 1};
}

gPoly<double> equation(&p_data.Space, &p_data.Lex);
gPoly<double> equation(&p_data.Space);
for (auto seq : p_data.sfg.GetSequences(p_sequence->player)) {
if (seq == p_sequence) {
continue;
Expand All @@ -86,8 +85,7 @@ gPoly<double> BuildSequenceVariable(ProblemData &p_data, const GameSequence &p_s

ProblemData::ProblemData(const BehaviorSupportProfile &p_support)
: sfg(p_support),
Space(sfg.GetSequences().size() - sfg.GetInfosets().size() - sfg.GetPlayers().size()),
Lex(&Space, lex)
Space(sfg.GetSequences().size() - sfg.GetInfosets().size() - sfg.GetPlayers().size())
{
for (auto sequence : sfg.GetSequences()) {
if (sequence->action &&
Expand All @@ -103,12 +101,12 @@ ProblemData::ProblemData(const BehaviorSupportProfile &p_support)

gPoly<double> GetPayoff(ProblemData &p_data, const GamePlayer &p_player)
{
gPoly<double> equation(&p_data.Space, &p_data.Lex);
gPoly<double> equation(&p_data.Space);

for (auto profile : p_data.sfg.GetContingencies()) {
auto pay = p_data.sfg.GetPayoff(profile, p_player);
if (pay != Rational(0)) {
gPoly<double> term(&p_data.Space, double(pay), &p_data.Lex);
gPoly<double> term(&p_data.Space, double(pay));
for (auto player : p_data.sfg.GetPlayers()) {
term *= p_data.variables.at(profile[player]);
}
Expand Down Expand Up @@ -160,7 +158,7 @@ std::list<MixedBehaviorProfile<double>> SolveSupport(const BehaviorSupportProfil
bool &p_isSingular, int p_stopAfter)
{
ProblemData data(p_support);
gPolyList<double> equations(&data.Space, &data.Lex);
gPolyList<double> equations(&data.Space);
IndifferenceEquations(data, equations);
LastActionProbPositiveInequalities(data, equations);

Expand Down
20 changes: 1 addition & 19 deletions src/solvers/enumpoly/gpoly.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,10 @@
#include "gpoly.imp"
#include "gambit.h"

template <> double gPoly<double>::String_Coeff(double nega)
{
std::string Coeff;
while ((charc >= '0' && charc <= '9') || charc == '.') {
Coeff += charc;
charnum++;
GetChar();
}
if (Coeff.empty()) {
return nega;
}
else {
return (nega * strtod(Coeff.c_str(), nullptr));
}
}

template class gPoly<double>;
template gPoly<double> operator+(const gPoly<double> &poly, const double &val);
template gPoly<double> operator*(const double &val, const gPoly<double> &poly);
template gPoly<double> operator*(const gPoly<double> &poly, const double &val);

template gPoly<double> TogDouble(const gPoly<double> &);
template gPoly<double> ToDouble(const gPoly<double> &);
template gPoly<double> NormalizationOfPoly(const gPoly<double> &);

template std::string &operator<<(std::string &, const gPoly<double> &);
Loading

0 comments on commit 15b956e

Please sign in to comment.