mirror of
https://github.com/BlackLight/nash.git
synced 2024-11-24 04:35:11 +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