Upload
benjamin-faerber
View
167
Download
0
Embed Size (px)
Citation preview
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
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
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
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
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
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
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
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
dpsm_simu.cpp
Customer::~Customer() {
}
Seite 9