First commit for nash

This commit is contained in:
BlackLight 2010-11-02 16:54:28 +01:00
commit 57e65981b6
6 changed files with 517 additions and 0 deletions

6
Makefile Normal file
View file

@ -0,0 +1,6 @@
all:
g++ -o nash main.cpp nash.cpp -g
clean:
rm tags
rm nash

62
README Normal file
View file

@ -0,0 +1,62 @@
This is a small software that simulates the behaviour of a set of individuals
placed (for sake of simplicity) over a matrix where each individual can choose
between two strategies:
- Being cooperative with the other individuals
- Being in competition with the other individuals
From a certain starting point, in which each individuals has its own strategy
independantly from the one chosen by the others, the algorithm goes on, and a
certain individual x changes its strategy if there is a neighbour having a
different strategy and a higher "gain" value (i.e. that strategy takes more
benefit). The algorithm is repeated as long as an equilibrium point is reached
(Nash's equilibrium) in which no individual will change its strategy anymore as
no change is convenient anymore. This balance point won't be always reached
anyway, and the algorithm recognizes a scenario that has no Nash's equilibrium
point when a loop occurs (i.e. when it takes in exam a configuration that was
already met).
Usage of the program: compile simply issuing `make', then start it with
./nash <environment_file> <coop_coop_gain> <coop_comp_gain> <comp_coop_gain> <comp_comp_gain>
where
- environment_file is a file containing the starting configuration of the
environment (an example is included in the file `environment'). In this file the
collaborating individuals are marked by a dot `.', and the ones in competition
are marked by a `X'. Starting from here you can easily create your environment
file;
- coop_coop_gain: Score gained when the individual x cooperates and its neighbour
cooperates as well;
- coop_comp_gain: Score gained when the individual x cooperates and its neighbour
is in competition;
- comp_coop_gain: Score gained when the individual x is in competition and its
neighbour cooperates;
- comp_comp_gain: Score gained when both the individual x and its neighbour are
in competition.
An example is the problem of the two prisoners:
- When A doesn't confess and B doesn't confess too, they both get 8 years of
prison (coop_coop_gain = -8);
- When A doesn't confess and B confesses, A gets 20 years of prison and B is
free (coop_comp_gain = -20);
- When A confesses and B doesn't, A is free and B gets 20 years of prison
(comp_coop_gain = 0);
- When both A and B confess, they both get 14 years of prison (comp_comp_gain =
-14).
For running a simulation of the two prisoners' problem over the example
environment just type
./nash environment -8 -20 0 -14
Have fun.

11
environment Normal file
View file

@ -0,0 +1,11 @@
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . X . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .

79
main.cpp Normal file
View file

@ -0,0 +1,79 @@
/*
* =====================================================================================
*
* Filename: main.cpp
*
* Description: Main file for the simulation of a Nash's environment
*
* Version: 0.1
* Created: 01/11/2010 13:23:03
* Revision: none
* Compiler: gcc
*
* Author: BlackLight (http://0x00.ath.cx), <blacklight@autistici.org>
* Licence: GNU GPL v.3
* Company: DO WHAT YOU WANT CAUSE A PIRATE IS FREE, YOU ARE A PIRATE!
*
* =====================================================================================
*/
#include <iostream>
#include <cstdlib>
#include "nash.h"
using std::cout;
using std::cerr;
using std::endl;
/**
* \brief Main function for the program
*/
int
main ( int argc, char *argv[] )
{
NashEnvironment *nash = NULL;
if ( argc < 6 )
{
cerr << "Usage: " << argv[0] << " <environment_file> <coop_coop_gain> <coop_comp_gain> <comp_coop_gain> <comp_comp_gain>" << endl;
return 1;
}
nash = new NashEnvironment ( argv[1] );
nash->init_costs (
strtod ( argv[2], NULL ),
strtod ( argv[3], NULL ),
strtod ( argv[4], NULL ),
strtod ( argv[5], NULL )
);
nash->print();
try
{
while ( nash->refresh_strategies() )
{
cout << endl;
for ( int i=0; i < nash->getCols(); i++ )
cout << "==";
cout << endl;
nash->print();
}
}
catch ( NashException e )
{
cerr << endl << e.what() << endl;
delete nash;
return 1;
}
cout << endl << "Nash's equilibrium configuration found" << endl;
delete nash;
return 0;
} /* ---------- end of function main ---------- */

259
nash.cpp Normal file
View file

@ -0,0 +1,259 @@
/*
* =====================================================================================
*
* Filename: nash.cpp
*
* Description: Simulation of a cooperative-competitive environemnt of individuals
* using Nash's models
*
* Version: 0.1
* Created: 31/10/2010 18:35:14
* Revision: none
* Compiler: gcc
*
* Author: BlackLight (http://0x00.ath.cx), <blacklight@autistici.org>
* Licence: GNU GPL v.3
* Company: DO WHAT YOU WANT CAUSE A PIRATE IS FREE, YOU ARE A PIRATE!
*
* =====================================================================================
*/
#include <iostream>
#include <fstream>
#include <vector>
#include "nash.h"
using std::cout;
using std::endl;
using std::vector;
using std::ifstream;
NashEnvironment::NashEnvironment ( int rows, int cols )
{
this->rows = rows;
this->cols = cols;
for ( int i=0; i < rows; i++ )
{
vector<nash_strategy> row;
for ( int j=0; j < cols; j++ )
{
row.push_back(coop);
}
matrix.push_back(row);
}
}
NashEnvironment::NashEnvironment ( const char *file )
{
vector<nash_strategy> row;
char ch;
rows = 0;
cols = 0;
ifstream in ( file );
if ( !in )
{
throw NashException("Could not open the specified file");
}
while ( !in.eof() )
{
ch = (char) in.get();
if ( ch == '\n' )
{
if ( cols == 0 )
{
cols = row.size();
} else {
if ( row.size() != 0 && cols != row.size() )
{
throw NashException("The size of the rows does not match");
}
}
if ( row.size() != 0 )
{
rows++;
matrix.push_back( row );
row.clear();
}
} else if ( ch == '.' ) {
row.push_back( coop );
} else if ( ch == 'X' ) {
row.push_back( comp );
}
}
if ( !row.empty() )
{
matrix.push_back( row );
row.clear();
}
if ( rows == 0 )
{
throw NashException("Invalid or empty strategy file");
}
}
const int
NashEnvironment::getRows()
{
return rows;
}
const int
NashEnvironment::getCols()
{
return cols;
}
void
NashEnvironment::init_costs ( double coop_coop, double coop_comp, double comp_coop, double comp_comp )
{
costs[coop][coop] = coop_coop;
costs[comp][comp] = comp_comp;
costs[comp][coop] = comp_coop;
costs[coop][comp] = coop_comp;
} /* ----- end of function nash_init_costs ----- */
void
NashEnvironment::print ()
{
for ( int i=0; i < rows; i++ )
{
for ( int j=0; j < cols; j++ )
{
cout << (( matrix[i][j] == coop ) ? "." : "X" ) << " ";
}
cout << endl;
}
} /* ----- end of function nash_print_matrix ----- */
void
NashEnvironment::update_utilities ( vector< vector< double > >& utilities )
{
for ( int x=0; x < rows; x++ )
{
for ( int y=0; y < cols; y++ )
{
utilities[x][y] = 0.0;
for ( int i = (( x == 0 ) ? x : x-1 ); i <= (( x == rows-1 ) ? x : x+1 ); i++ )
{
for ( int j = (( y == 0 ) ? y : y-1 ); j <= (( y == cols-1 ) ? y : y+1 ); j++ )
{
if ( !( x == i && y == j ))
{
utilities[x][y] += costs [matrix[x][y]] [matrix[i][j]];
}
}
}
}
}
}
bool
NashEnvironment::refresh_strategies ()
{
double best_utility = 0.0;
int best_x = 0, best_y = 0;
vector< vector<int> > changes;
vector< vector<double> > utilities;
for ( int i=0; i < rows; i++ )
{
vector<double> row(cols);
utilities.push_back(row);
}
update_utilities ( utilities );
for ( int x=0; x < rows; x++ )
{
for ( int y=0; y < cols; y++ )
{
best_x = x;
best_y = y;
best_utility = utilities[best_x][best_y];
for ( int i = (( x == 0 ) ? x : x-1 ); i <= (( x == rows-1 ) ? x : x+1 ); i++ )
{
for ( int j = (( y == 0 ) ? y : y-1 ); j <= (( y == cols-1 ) ? y : y+1 ); j++ )
{
if ( !( x == i && y == j ))
{
if ( utilities[i][j] > best_utility )
{
best_x = i;
best_y = j;
best_utility = utilities[best_x][best_y];
}
}
}
}
if ( matrix[best_x][best_y] != matrix[x][y] )
{
vector<int> pair(2);
pair[0] = x;
pair[1] = y;
changes.push_back (pair);
}
}
}
for ( int i=0; i < changes.size(); i++ )
{
matrix[changes[i][0]][changes[i][1]] = ( matrix[changes[i][0]][changes[i][1]] == coop ) ? comp : coop;
}
if ( changes.size() > 0 )
{
if ( check_loop() )
{
throw NashException ("Loop detected - No Nash's equilibrium is possible for this configuration");
}
}
visited_combinations.push_back(matrix);
return ( changes.size() > 0 );
} /* ----- end of function nash_refresh_strategies ----- */
bool
NashEnvironment::check_loop ()
{
bool found = false;
for ( int n=0; n < visited_combinations.size(); n++ )
{
found = true;
for ( int i=0; i < rows && found; i++ )
{
for ( int j=0; j < cols && found; j++ )
{
if ( matrix[i][j] != visited_combinations[n][i][j] )
{
found = false;
}
}
}
if ( found )
{
return true;
}
}
return false;
} /* ----- end of function check_loop ----- */

100
nash.h Normal file
View file

@ -0,0 +1,100 @@
/*
* =====================================================================================
*
* Filename: nash.h
*
* Description: Header file for the simulation of Nash's model
*
* Version: 0.1
* Created: 01/11/2010 13:20:44
* Revision: none
* Compiler: gcc
*
* Author: BlackLight (http://0x00.ath.cx), <blacklight@autistici.org>
* Licence: GNU GPL v.3
* Company: DO WHAT YOU WANT CAUSE A PIRATE IS FREE, YOU ARE A PIRATE!
*
* =====================================================================================
*/
#include <vector>
#include <exception>
typedef enum { coop, comp } nash_strategy;
class NashException : public std::exception
{
const char *message;
public:
NashException ( const char *m )
{
message = m;
}
virtual const char* what()
{
return message;
}
};
class NashEnvironment
{
int rows;
int cols;
double costs[2][2];
std::vector< std::vector< nash_strategy > > matrix;
std::vector< std::vector< std::vector< nash_strategy > > > visited_combinations;
/**
* \brief Verify if a certain scenario has already been visited, for avoiding loops in environments without Nash's balance
* \return True if the current scenario was already analyzed, false otherwise
*/
bool check_loop ();
/**
* \brief Update the utility costs on the matrix
* \param utilities Reference to the utilities matrix to be updated
*/
void update_utilities ( std::vector< std::vector<double> >& utilities );
public:
/**
* \brief Constructor for the class
* \param rows Rows of the Nash environment's matrix
* \param cols Cols of the Nash environment's matrix
*/
NashEnvironment ( int rows, int cols );
/**
* \brief Constructor for the class
*/
NashEnvironment ( const char *file );
/**
* \brief Number of rows in the matrix
*/
const int getRows();
/**
* \brief Number of cols in the matrix
*/
const int getCols();
/**
* \brief Initialize the costs of the matrix of strategy costs
*/
void init_costs ( double coop_coop, double coop_comp, double comp_coop, double comp_comp );
/**
* \brief Print the current status of the matrix of strategies
*/
void print ();
/**
* \brief Refresh the matrix of the utility values
* \return True if there were strategy changes, false otherwise
*/
bool refresh_strategies ();
};