9
dpsm_simu.cpp #include "dpsm_simu.hpp" #include "tools.hpp" #include <cstdlib> #include <ctime> #include <iostream> #include <fstream> #include <string> #include <vector> #include <cmath> #include <stdio.h> #include <cstdarg> /*------------------------ Simulation -------------------------*/ void DPSM::Start() { int salesm_id, cust_id; for (it = 0; it < num_iterations; it++) { //Kaufer laufen lassen und pruefen, ob sie einen Verkaeufer treffen for (cust_id = 0; cust_id < num_customers; cust_id++) { if (cust[cust_id].time_to_sleep > 0) { cust[cust_id].time_to_sleep--; continue; } cust[cust_id].Walk(grid_size); salesm_id = CheckPosition(cust[cust_id].x, cust[cust_id].y); if (salesm_id != -1) { //Kaeufer und Kunde befinden sich an gleicher Position CheckDeal(cust_id, salesm_id); salesm[salesm_id].visits++; } } //Verkaeufer preise anpassen lassen for (salesm_id = 0; salesm_id < num_salesman; salesm_id++) { salesm[salesm_id].pAdjust(it); //Loggen if (it % log_bin_size == log_bin_size - 1) { stat.LogSalesman(salesm_id, salesm[salesm_id].earnings, salesm[salesm_id].p, salesm[salesm_id].sales, salesm[salesm_id].visits); } } } } Seite 1

Dpsm simu.cpp

Embed Size (px)

Citation preview

Page 1: Dpsm simu.cpp

dpsm_simu.cpp

#include "dpsm_simu.hpp"

#include "tools.hpp"

#include <cstdlib>

#include <ctime>

#include <iostream>

#include <fstream>

#include <string>

#include <vector>

#include <cmath>

#include <stdio.h>

#include <cstdarg>

/*------------------------ Simulation -------------------------*/

void DPSM::Start() { int salesm_id, cust_id;

for (it = 0; it < num_iterations; it++) { //Kaufer laufen lassen und pruefen, ob sie einen Verkaeufer

treffen for (cust_id = 0; cust_id < num_customers; cust_id++) { if (cust[cust_id].time_to_sleep > 0) { cust[cust_id].time_to_sleep--; continue; }

cust[cust_id].Walk(grid_size);

salesm_id = CheckPosition(cust[cust_id].x,

cust[cust_id].y); if (salesm_id != -1) { //Kaeufer und Kunde befinden sich

an gleicher Position CheckDeal(cust_id, salesm_id); salesm[salesm_id].visits++; } }

//Verkaeufer preise anpassen lassen for (salesm_id = 0; salesm_id < num_salesman; salesm_id++) { salesm[salesm_id].pAdjust(it);

//Loggen if (it % log_bin_size == log_bin_size - 1) { stat.LogSalesman(salesm_id,

salesm[salesm_id].earnings, salesm[salesm_id].p, salesm[salesm_id].sales,

salesm[salesm_id].visits); } } }

}

Seite 1

Page 2: Dpsm simu.cpp

dpsm_simu.cpp

void DPSM::InitPeople() { int i;

//Kaeufer InitCustomer();

//Verkaeufer salesm.clear(); salesm.resize(num_salesman); for (i = 0; i < num_salesman; i++) { do { salesm[i].Init(grid_size); } //Prueft, ob sich bereits ein Verkaeufer an (x,y) befindet while (CheckPosition(salesm[i].x, salesm[i].y, i) != -1); }

}

void DPSM::InitCustomer() { cust.clear(); cust.resize(num_customers); for (int i = 0; i < num_customers; i++) { cust[i].Init(grid_size); }

}

void DPSM::InitStats() { stat.Init(&grid_size, &log_bin_size, &num_iterations, &num_customers,

&num_salesman);

}

int DPSM::CheckPosition(int x, int y, int self_id) { for (int i = 0; i < num_salesman; i++) { if (salesm[i].x == x && salesm[i].y == y && i != self_id) { return i; } } return -1;

}

void DPSM::CheckDeal(int &cust_id, int &salesm_id) { if (Customer::memory == 0) { //1. Version //Prueft, ob Nutzen > Kosten und ob Kaeufer schlaeft if (cust[cust_id].theta > salesm[salesm_id].p &&

cust[cust_id].time_to_sleep == 0) { //Prueft, ob ob er kauft if

(BernoulliDistr(cust[cust_id].BuyProbability(salesm[salesm_id].p))) { salesm[salesm_id].Sell(); cust[cust_id].Buy(grid_size); } }

Seite 2

Page 3: Dpsm simu.cpp

dpsm_simu.cpp } else { //2. Version std::vector<int> &log = cust[cust_id].log_smid; int size = log.size(); log.push_back(salesm_id);

if (size >= Customer::memory) { //Kaufen std::vector<double> prob(size);

for (int i = 0; i < size; i++) { prob[i] = (i == 0 ? 0 : prob[i-1]) +

exp(Customer::mem_k * (cust[cust_id].theta - salesm[log[i]].p));

//std::cout << prob[i] << "\t"; } //std::cout << std::endl;

double rnd = drand48() * prob[size - 1]; int id_min = 0;

for (int i = 0; i < size; i++) { if (rnd < prob[i]) { id_min = log[i]; break; } }

if (cust[cust_id].theta >= salesm[id_min].p) { salesm[id_min].Sell(); cust[cust_id].Buy(grid_size); }

log.clear(); }

cust[cust_id].Buy(grid_size); }

}

void DPSM::ShowEarnings() { std::cout << std::endl; for (int i = 0; i < num_salesman; i++) { std::cout << i << " - " << salesm[i].earnings << " - (" << salesm[i].x << ", " << salesm[i].y << ")" << std::endl; }

}

DPSM::DPSM() { srand48(time(NULL));

//Standard-Parameter setzen num_iterations = 1000*1000;

Seite 3

Page 4: Dpsm simu.cpp

dpsm_simu.cpp Customer::sleep_time = 0; num_customers = 50; num_salesman = 1; grid_size = 50; log_bin_size = num_iterations / 250; file_prefix = "out"; file_path = "./output/";

}

DPSM::~DPSM() {

}

/*------------------------ Salesman -------------------------*/

void Salesman::Init(int &grid_size) { x = int (drand48() * grid_size); y = int (drand48() * grid_size);

p = drand48() * (Customer::log_norm ? Customer::log_norm_ev : 1); earnings = 0; sales = 0; visits = 0; strategy = 0; ipr = 1000;

}

void Salesman::Sell() { earnings = earnings + p; sales++;

}

void Salesman::pAdjust(int it) { if (it % ipr == 0) { log_earnings.push_back(earnings); log_p.push_back(p);

if (strategy == 0) adjConst(); if (strategy == 1) adjPara(); if (strategy == 2) adjI(); if (strategy == 3) adjClimb(); }

}

void Salesman::SetStrategy(int t_ipr, int t_strategy, ...) { ipr = t_ipr; strategy = t_strategy;

va_list parameter;// Zeiger auf Argumentliste va_start(parameter, t_strategy);

if (strategy == 0) { //Konstanter preis

Seite 4

Page 5: Dpsm simu.cpp

dpsm_simu.cpp p = va_arg(parameter, double); } else if (strategy == 1) { //Mittelwert / Random-Walk adjParaM = va_arg(parameter, double); //1. Schrittweite adjParaN = va_arg(parameter, int); //Mittelungshorizont adjParaP = 2; } else if (strategy == 2) { //Mittelwert adjI_N = 8; adjI_size = 0.5; } else if (strategy == 3) { //Bergsteiger adjClimbSW = va_arg(parameter, double); } else strategy = 0;

va_end(parameter);

}

/*--------------------------------------------*/

//Anpassungs-Algorithmen

void Salesman::adjConst() {

}

void Salesman::adjPara() { int p_size = log_p.size() - 1; int maxi = (p_size > adjParaN ? adjParaN : p_size);

if (earnings_at(0) < 0) { p = p_at(1); adjParaM = fabs(adjParaM); p = p + (drand48())*adjParaM; } else if (earnings_at(0) == 0) { adjParaM = fabs(adjParaM) * (-1); p = p + (drand48())*adjParaM; } else if (earnings_at(0) < earnings_at(1)) { //Verlust adjParaM = adjParaM * (-1);

//Mittelwerte double sum_w = 0, sum_pw = 0; double weight = 0, max_e = 0, max_p = 0; for (int i = 0; i < maxi; i++) { weight = pow(earnings_at(i), 5.0);

sum_pw += weight * p_at(i); sum_w += weight;

if (earnings_at(i) > max_e) { max_e = earnings_at(i); max_p = p_at(i); } }

Seite 5

Page 6: Dpsm simu.cpp

dpsm_simu.cpp //Mittelwert setzen if (sum_w > 0) { p = 0.5 * sum_pw / sum_w + 0.5 * max_p; } } else { //Gewinn p = p + (drand48())*adjParaM; }

if (p <= 0) { p = (drand48())*fabs(adjParaM); }

//std::cout << p_at(0) << "\t" << earnings_at(0) << std::endl;

}

void Salesman::adjI() {

int p_size = log_p.size() - 1; int maxi = (p_size > adjI_N*10 ? adjI_N*10 : p_size);

double sum_w = 0, sum_pw = 0, weight, max_e = 0, max_p = 0;

for (int i = 0; i < maxi; i++) { weight = (earnings_at(i) > 0 ? pow(earnings_at(i), 5.0)

: 0);

if (earnings_at(i) > max_e && i <= adjI_N * 2) { max_e = earnings_at(i); max_p = p_at(i); }

sum_pw += weight * p_at(i); sum_w += weight; }

do { if (sum_w > 0) { p = sum_pw / sum_w + (drand48()*2 -

1)*adjI_size; } else { p = p + (drand48()*2 - 1)*adjI_size; } } while (p <= 0);

adjI_size = adjI_size * 0.995;

}

void Salesman::adjClimb() { if (earnings_at(0) / earnings_at(1) <= 1) { //Verlust adjClimbSW = adjClimbSW * (-1); p = p_at(1);

Seite 6

Page 7: Dpsm simu.cpp

dpsm_simu.cpp } else { //Gewinn p = p + drand48()*adjClimbSW; }

std::cout << p_at(0) << "\t" << earnings_at(0) << std::endl;

}

/*--------------------------------------------*/

double Salesman::earnings_at(int n) { int j = log_earnings.size() - 1; if (n >= j) return 0; return (log_earnings.at(j - n) - log_earnings.at(j-1 - n));

}

double Salesman::p_at(int n) { int j = log_p.size() - 1; if (n > j) return 0; return log_p.at(j - n);

}

Salesman::Salesman(){

}

Salesman::~Salesman(){

}

/*------------------------ Customer -------------------------*/

int Customer::sleep_time;

int Customer::walk_time;

double Customer::parsimony;

bool Customer::log_norm;

double Customer::log_norm_ev;

double Customer::log_norm_var;

int Customer::memory;

double Customer::mem_k;

//Initialisieren

Customer::Customer() {

}

void Customer::Init(int &grid_size) { x = int (drand48() * grid_size); y = int (drand48() * grid_size);

if (Customer::log_norm) { theta = LogNormal(Customer::log_norm_ev,

Customer::log_norm_var); } else {

Seite 7

Page 8: Dpsm simu.cpp

dpsm_simu.cpp theta = drand48(); }

//Konfig time_to_sleep = 0;

}

//Random Walk

void Customer::Walk(int &grid_size) { double rnd = drand48();

//Wohin? if (rnd < 0.25) y = y + 1; else if (rnd < 0.5) x = x + 1; else if (rnd < 0.75) y = y - 1; else x = x - 1;

//Am Rand? // if (x < 0) x = 0; // if (x >= grid_size) x = grid_size - 1; // if (y < 0) y = 0; // if (y >= grid_size) y = grid_size - 1;

if (x < 0) x = grid_size - 1; if (x >= grid_size) x = 0; if (y < 0) y = grid_size - 1; if (y >= grid_size) y = 0;

return;

}

//Kunde hat gekauft

void Customer::Buy(int &grid_size) {

if (Customer::walk_time < 0) { x = int (drand48() * grid_size); y = int (drand48() * grid_size); } else { for (int i = 0; i < Customer::walk_time; i++) { Walk(grid_size); } }

time_to_sleep = Customer::sleep_time;

}

//Wahrscheinlichkeit für Kauf

double Customer::BuyProbability(double p) { return pow(theta - p, Customer::parsimony);

}

Seite 8

Page 9: Dpsm simu.cpp

dpsm_simu.cpp

Customer::~Customer() {

}

Seite 9