#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <random>
#include <algorithm>
struct Customer{
double x;
double y;
double size;
};
struct Shop{
double x;
double y;
double cost;
double capacity;
};
static double distance(const std::pair<double, double> &from, const std::pair<double, double> &to){
return std::sqrt((from.first - to.first) * (from.first - to.first) + (from.second - to.second) * (from.second - to.second));
}
class Population{
public:
Population(size_t population_sz, const std::vector<Customer> &custom, const std::vector<Shop> &sh, const std::vector<std::vector<double>> &d): population_size(population_sz), customer_size(custom.size()), shop_size(sh.size()), shops(sh), customers(custom), dist_matrix(d){
population.resize(population_sz, std::vector<int>(customer_size));
std::random_device rnd_device;
std::mt19937 mersenne_engine {rnd_device()};
int sz = static_cast<int>(shop_size - 1);
std::uniform_int_distribution<int> dist {0, sz};
for (int i = 0; i < population_sz; ++i){
auto gen = [&dist, &mersenne_engine](){
return dist(mersenne_engine);
};
std::vector<int> vec(customer_size);
std::generate(std::begin(vec), std::end(vec), gen);
population[i] = vec;
}
population_candidates = population;
}
double count_one_fitness(size_t index){
double fitness = 0.0;
std::vector<double> open(shop_size, 0.0);
for (size_t i = 0; i < customer_size; ++i){
int shop = population[index][i];
if (open[shop] < 0.0000001){
fitness += shops[shop].cost;
}
fitness += dist_matrix[shop][i];
open[shop] += customers[i].size;
}
for (size_t i = 0; i < shop_size; ++i){
double delta = shops[i].capacity - open[i];
if (delta < 0){
fitness += delta * fitness * 0.3;
}
}
return fitness;
}
double one_fitness(std::vector<int>& sol){
double fitness = 0.0;
std::vector<double> open(shop_size, 0.0);
for (size_t i = 0; i < customer_size; ++i){
int shop = sol[i];
if (open[shop] < 0.0000001){
fitness += shops[shop].cost;
}
fitness += dist_matrix[shop][i];
open[shop] += customers[i].size;
}
for (size_t i = 0; i < shop_size; ++i){
double delta = shops[i].capacity - open[i];
if (delta < 0){
fitness += delta * fitness * 0.3;
}
}
return fitness;
}
std::vector<int> breeding_one_iteration(size_t parent1, size_t parent2, const std::vector<size_t> &indexes){
std::vector<int> children1 = population[parent1];
std::vector<int> children2 = population[parent2];
for (unsigned long index : indexes){
children1[index] = population[parent2][index];
children2[index] = population[parent1][index];
}
double f1 = one_fitness(children1);
double f2 = one_fitness(children2);
if (f1 < f2){
return children1;
}
return children2;
}
std::vector<int> mutation_one_iteration(size_t parent, const std::vector<size_t> &indexes, const std::vector<int> &new_meaning) {
std::vector<int> children = population[parent];
for (int i = 0; i < indexes.size(); ++i) {
children[indexes[i]] = new_meaning[i];
}
return children;
}
std::vector<std::vector<int>> breeding(size_t number_candidates){
std::vector<size_t> ind(customer_size);
for (int i = 0; i < customer_size; ++i){
ind[i] = i;
}
std::vector<std::vector<int>> new_population(number_candidates);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<size_t> distrib(0, population_size - 1);
for (int i = 0; i < number_candidates; ++i){
size_t p1 = distrib(gen);
size_t p2 = distrib(gen);
std::shuffle(ind.begin(), ind.end(), gen);
new_population[i] = breeding_one_iteration(p1, p2, std::vector<size_t> { ind.begin(), ind.begin() + customer_size / 2 + 1 });
}
return new_population;
}
std::vector<std::vector<int>> mutations(size_t number_candidates) {
std::vector<std::vector<int>> new_population(number_candidates);
std::random_device rd;
std::mt19937 gen(rd());
std::vector<size_t> ind(customer_size);
for (int i = 0; i < customer_size; ++i){
ind[i] = i;
}
std::mt19937 mersenne_engine {rd()};
int sz = static_cast<int>(shop_size - 1);
std::uniform_int_distribution<int> dist {0, sz};
std::uniform_int_distribution<size_t> distrib(0, population_size - 1);
for (int i = 0; i < number_candidates; ++i) {
size_t p = distrib(gen);
auto gen = [&dist, &mersenne_engine](){
return dist(mersenne_engine);
};
std::vector<int> vec(customer_size / 4 + 1);
std::generate(std::begin(vec), std::end(vec), gen);
new_population[i] = mutation_one_iteration(p, std::vector<size_t> { ind.begin(), ind.begin() + customer_size / 4 + 1}, vec);
}
return new_population;
}
void one_iteration_genetic_algorithm(){
// хочется в каждой итерации генерить разное количество новых кандидатов с помощью селекции/мутации
}
private:
size_t customer_size;
size_t shop_size;
size_t population_size;
std::vector<std::vector<int>> population;
std::vector<Shop> shops;
std::vector<Customer> customers;
std::vector<std::vector<int>> population_candidates;
std::vector<std::vector<double>> dist_matrix;
};
int main() {
std::ifstream in;
int n;
int m;
in.open("/home/katfresal/CLionProjects/Facility location/data/");
in >> n >> m;
std::vector<Shop> shops(n);
std::vector<Customer> customers(m);
for (int i = 0; i < n; ++i){
in >> shops[i].cost >>shops[i].capacity >> shops[i].x >> shops[i].y;
}
for (int i = 0; i < m; ++i){
in >> customers[i].size >> customers[i].x >> customers[i].y;
}
in.close();
std::vector<std::vector<double>> dist_matrix(n, std::vector<double>(m));
for (int i = 0; i < n; ++i){
for (int j = 0; j < m; ++j){
dist_matrix[i][j] = distance({shops[i].x, shops[i].y}, {customers[j].x, customers[j].y});
}
}
}