mirror of
https://github.com/BlackLight/nash.git
synced 2024-12-26 17:25:10 +01:00
First commit for nash
This commit is contained in:
commit
57e65981b6
6 changed files with 517 additions and 0 deletions
6
Makefile
Normal file
6
Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
all:
|
||||
g++ -o nash main.cpp nash.cpp -g
|
||||
|
||||
clean:
|
||||
rm tags
|
||||
rm nash
|
62
README
Normal file
62
README
Normal 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
11
environment
Normal file
|
@ -0,0 +1,11 @@
|
|||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . X . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
||||
. . . . . . . . . . .
|
79
main.cpp
Normal file
79
main.cpp
Normal 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
259
nash.cpp
Normal 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
100
nash.h
Normal 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 ();
|
||||
};
|
||||
|
Loading…
Reference in a new issue