129 lines
3.7 KiB
C++
129 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include <chrono>
|
|
#include <thread>
|
|
#include <fstream>
|
|
#include <mpi.h>
|
|
|
|
#include "comm_tag.h"
|
|
#include "../light.hpp"
|
|
#include "../utils/cmdline.h"
|
|
#include "../utils/easylogging++.h"
|
|
#include "../paras.hpp"
|
|
#include "heartbeat.h"
|
|
|
|
|
|
|
|
void leader_main(light* S, int num_procs, int rank) {
|
|
|
|
auto clk_st = std::chrono::high_resolution_clock::now();
|
|
|
|
el::Configurations defaultConf;
|
|
defaultConf.setGlobally(el::ConfigurationType::Format, "c %level [leader] %msg");
|
|
el::Loggers::reconfigureLogger("default", defaultConf);
|
|
|
|
LOG(INFO) << "start logging powered by easylogging++";
|
|
|
|
S->opt->print_change();
|
|
|
|
LOG(INFO) << "c [leader] preprocess(simplify) input data";
|
|
|
|
// 进行化简
|
|
auto pre = new preprocess();
|
|
char *filename = const_cast<char*>(S->opt->instance.c_str());
|
|
int start = pre->do_preprocess(filename);
|
|
|
|
// 给每个 worker 发布是否启动计算流程的信息
|
|
for(int i=1; i<num_procs; i++) {
|
|
MPI_Send(&start, 1, MPI_INT, i, START_TAG, MPI_COMM_WORLD);
|
|
}
|
|
|
|
// preprocess 证明了UNSAT 则不需要启动云计算
|
|
if(!start) {
|
|
LOGGER->info("UNSAT!!!!!! by preprocess");
|
|
return;
|
|
}
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "p cnf " << pre->vars << " " << pre->clause.size() << std::endl;
|
|
for (int i = 1; i <= pre->clauses; i++) {
|
|
int l = pre->clause[i].size();
|
|
for (int j = 0; j < l; j++)
|
|
ss << pre->clause[i][j] << " ";
|
|
ss << "0" << std::endl;
|
|
}
|
|
|
|
const auto& str_ref = ss.str();
|
|
char* cstr = const_cast<char *>(str_ref.c_str());
|
|
|
|
LOGGER->info("hand out length of cnf instance to all nodes");
|
|
|
|
int cnf_length = str_ref.size();
|
|
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
|
|
MPI_Bcast(&cnf_length, 1, MPI_INT, 0, MPI_COMM_WORLD);
|
|
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
|
|
LOGGER->info("hand out cnf instance to all nodes");
|
|
|
|
MPI_Bcast(cstr, cnf_length, MPI_CHAR, 0, MPI_COMM_WORLD);
|
|
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
|
|
LOGGER->info("hand out done!");
|
|
|
|
int is_sat;
|
|
MPI_Request solved;
|
|
MPI_Status status;
|
|
MPI_Irecv(&is_sat, 1, MPI_INT, MPI_ANY_SOURCE, SOLVED_REPORT_TAG, MPI_COMM_WORLD, &solved);
|
|
|
|
// waiting for results:
|
|
while(true) {
|
|
|
|
// 检测时间是否超限
|
|
auto clk_now = std::chrono::high_resolution_clock::now();
|
|
int solve_time = std::chrono::duration_cast<std::chrono::seconds>(clk_now - clk_st).count();
|
|
if (solve_time >= S->opt->times) {
|
|
LOGGER->info("solve time out");
|
|
break;
|
|
}
|
|
|
|
int flag;
|
|
// check if problem solved
|
|
if(MPI_Test(&solved, &flag, &status) == MPI_SUCCESS && flag == 1) {
|
|
|
|
MPI_Request temp[num_procs];
|
|
|
|
// send terminal signal to all nodes
|
|
for(int i=1; i<num_procs; i++) {
|
|
if(i != status.MPI_SOURCE) {
|
|
MPI_Isend(NULL, 0, MPI_INT, i, TERMINATE_TAG, MPI_COMM_WORLD, &temp[i]);
|
|
}
|
|
}
|
|
|
|
// send signal for getting solution(model) when sat
|
|
|
|
if(is_sat) {
|
|
LOGGER->info("recived model size: %v", pre->vars);
|
|
LOGGER->info("SAT!!!!!!");
|
|
|
|
MPI_Send(NULL, 0, MPI_INT, status.MPI_SOURCE, MODEL_REPORT_TAG, MPI_COMM_WORLD);
|
|
int* sol = new int[pre->vars];
|
|
MPI_Recv(sol, pre->vars, MPI_INT, status.MPI_SOURCE, MODEL_REPORT_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
|
|
|
for(int i=0; i<pre->vars; i++) {
|
|
printf("%d ", sol[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
delete []sol;
|
|
} else {
|
|
LOGGER->info("UNSAT!!!!!!");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} |