diff --git a/README.md b/README.md index 7b22a1ae12c12bee6b15b785a74bf6a3de6151b0..d2016ffcfd61e8a21d247e604d646d87e594518c 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,14 @@ make # ToDo * ブロックを詰める作業の精度向上(現状,右下にスペースが生まれるような結果になりやすい) -* 端点を含まないブロックへの対応 -* 組み込みシステム(PYNQ)上での実行 -* ソルバのハードウェア化 +* ~~端点を含まないブロックへの対応~~ +* ~~組み込みシステム(PYNQ)上での実行→Python3からsolverを呼び出すコードを開発~~ +* Ubuntu上でソルバを動作させたときの実行時間計測(NotePC, PYNQ-Z1) +* ~~ソルバのハードウェア化~~ +* ハードウェアを呼び出すためのwrapperコードを開発(現状jupyter上での実行) +* **ソルバの高速化** +* 求解途中であっても解を出力できるようにする +* **自作問題の作成** # Update log * 2019/08/09 diff --git a/solver_python/Makefile b/solver_python/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1d41368ebeb6c20c8cdf6ac512022c700cbeb887 --- /dev/null +++ b/solver_python/Makefile @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = main.cpp io.cpp solver.cpp tools.cpp +CXX = g++ +CXXFLAGS = -std=c++11 -O3 + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/solver_python/README.md b/solver_python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e46bcb2a55d00a6fa7be6477f3f937aacc05ed40 --- /dev/null +++ b/solver_python/README.md @@ -0,0 +1,84 @@ +# Environment +* PYNQ-Z1 (v2.4) (Release 2019_02_21) +* PYNQ Linux, based on Ubuntu 18.04 +* Python 3.6.5 + +To confirm, +``` +cat REVISION +cat /etc/lsb-release +python3 --version +``` + +# Python solver based on C++ programs + +C/C++ wrapper for python + +[Reference] +* https://docs.python.org/ja/3/c-api/index.html +* https://cpp-learning.com/python_c_api_step1/ (勉強になる) +* https://cpp-learning.com/python_c_api_step2/ (勉強になる) +* http://codeit.blog.fc2.com/blog-entry-9.html (numpy) + +## Setup + +Check include file in `py_wrapper.hpp` & `solver.hpp` (python version) + +``` +#include "/usr/include/python3.6m/Python.h" +#include "/usr/include/python3.6m/numpy/arrayobject.h" +#include "/usr/include/python3.6m/numpy/arrayscalars.h" +``` + +If there exist no files in `/usr/include/python3.6m`, type commands as follows: + +``` +sudo apt-get install python3-dev +sudo apt-get install python3-numpy +``` + +Type command as follows: + +``` +sudo python3 setup.py install +``` + +To confirm, type `pip3 freeze`. `mySolverModule==1.0.0` will be listed. + +[Uninstall] +``` +sudo rm -rf build +sudo pip3 uninstall mySolverModule +``` + +## Run + +``` +python3 main.py -p input-Q-file(.txt) [-s seed-value] [-o output-A-file(.txt)] +``` + +# C++ solver + +## Setup + +``` +make # g++ +``` + +or + +``` +make -f Makefile.arm ## arm-linux-gnueabihf-g++ +``` + +## Run + +``` +./sim -p input-Q-file(.txt) [-s seed-value] [-o output-A-file(.txt)] +``` + +# 実行時間比較 + +例題(sample_Q.txt),シード値デフォルト(214) + +**TODO** \ No newline at end of file diff --git a/solver_python/io.cpp b/solver_python/io.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e38488cdcdb9c1baffa232c087af7827ee3a8a8 --- /dev/null +++ b/solver_python/io.cpp @@ -0,0 +1,287 @@ +#include "io.hpp" + +void read_problem(const char *f_name, short int *W, short int *H, short int *blocks, short int *line_num, short int block_info[][5][3], short int line_info[][2][5]) { + + ifstream inputfile(f_name); + if(!inputfile) { + cout << f_name << ": Cannot open" << endl; + exit(1); + } + + for(int i = 0; i < MAX_BLOCKS+1; i++) { + for(int j = 0; j < 5; j++) { + for(int k = 0; k < 3; k++) { + block_info[i][j][k] = -1; + } + } + } + for(int i = 0; i < MAX_LINES+1; i++) { + for(int j = 0; j < 2; j++) { + for(int k = 0; k < 5; k++) { + line_info[i][j][k] = -1; + } + } + } + *line_num = 0; + + int now_block = 0, count; + short int size_x = -1, size_y = -1, now_x, now_y, num; + while(1) { + string line, tmp; + string::size_type pos; + + if(!getline(inputfile, line)) break; + if(line.find("\n") != string::npos || line.find("\r") != string::npos) { + line.replace(line.length()-1, 1, ""); // Remove '\n' or '\r' + } + + int len = line.length(); + if(len == 0) continue; + + if(line.find("SIZE") != string::npos) { + replace(line.begin(), line.end(), 'X', ' '); + istringstream iss(line); + iss >> tmp >> *W >> *H; + continue; + } + else if(line.find("BLOCK_NUM") != string::npos) { + istringstream iss(line); + iss >> tmp >> *blocks; + continue; + } + else if(line.find("BLOCK") != string::npos) { + now_block++; + replace(line.begin(), line.end(), 'X', ' '); + istringstream iss(line); + iss >> tmp >> size_x >> size_y; + now_y = 0; + count = 1; + block_info[now_block][0][0] = size_x; + block_info[now_block][0][1] = size_y; + continue; + } + + // Replace ' ' -> "" + pos = 0; + while((pos = line.find(' ', pos)) != string::npos) { + line.replace(pos, 1, ""); + } + // Replace '+' -> "-1" + pos = 0; + while((pos = line.find('+', pos)) != string::npos) { + line.replace(pos, 1, "-1"); + } + // Replace ',' -> " " + pos = 0; + while((pos = line.find(',', pos)) != string::npos) { + line.replace(pos, 1, " "); + } + + istringstream iss(line); + for(now_x = 0; now_x < size_x; now_x++) { + iss >> num; + if(num > 0) { + block_info[now_block][count][0] = now_x; + block_info[now_block][count][1] = now_y; + block_info[now_block][count][2] = num; + if(line_info[num][0][0] == -1) { line_info[num][0][0] = now_block; } + else if(line_info[num][1][0] == -1) { line_info[num][1][0] = now_block; } + else { cout << "Error(RE0): Line#" << num << endl; exit(1); } + if(num > *line_num) { *line_num = num; } + count++; + } + else if(num < 0) { + block_info[now_block][count][0] = now_x; + block_info[now_block][count][1] = now_y; + block_info[now_block][count][2] = 0; + count++; + } + } + now_y++; + } + cout << "W: " << *W << ", H: " << *H << endl; + + /// Print block information /// + cout << "== Block information ==" << endl; + cout << "#Blocks = " << *blocks << endl; + for(int i = 1; i <= *blocks; i++) { + short int sx = block_info[i][0][0]; + short int sy = block_info[i][0][1]; + cout << "Block#" << i << ": (" << sx << ", " << sy << ")" << endl; + + if(sx == 1 && sy == 1) { // monomino + short int tx = block_info[i][1][0]; + short int ty = block_info[i][1][1]; + short int tn = block_info[i][1][2]; + cout << "- (" << tx << ", " << ty << ") " << tn << endl; + } + else { + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + cout << "- (" << tx << ", " << ty << ") " << tn << endl; + } + } + } + /// Print block information /// +} + +void extract_line_info(short int line_num, short int blocks, short int block_info[][5][3], short int line_info[][2][5]) { + + short int lines_x[4], lines_y[4]; // # of nums in a block for X- & Y- axes + for(int i = 1; i <= blocks; i++) { + short int sx = block_info[i][0][0]; + short int sy = block_info[i][0][1]; + + if(sx == 1 && sy == 1) { // monomino + //short int tx = block_info[i][1][0]; + //short int ty = block_info[i][1][1]; + short int tn = block_info[i][1][2]; + + if(tn == 0) continue; + + short int n_idx = 0; + while(line_info[tn][n_idx][1] != -1) { + n_idx++; + if(n_idx >= 2) { cout << "Error(EL0): Line#" << tn << endl; exit(1); } + } + line_info[tn][n_idx][LE] = 2; + line_info[tn][n_idx][TO] = 2; + line_info[tn][n_idx][RI] = 2; + line_info[tn][n_idx][BO] = 2; + + continue; + } + + for(short int p = 0; p < 4; p++) lines_x[p] = 0; + for(short int q = 0; q < 4; q++) lines_y[q] = 0; + + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + if(tn > 0) { + lines_x[tx] += 1; + lines_y[ty] += 1; + } + } + + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + + if(tn == 0) continue; + + short int n_idx = 0; + while(line_info[tn][n_idx][1] != -1) { + n_idx++; + if(n_idx >= 2) { cout << "Error(EL1): Line#" << tn << endl; exit(1); } + } + + short int compe_cost, wall_cost; + // Map to left + compe_cost = 2; + compe_cost += lines_x[tx] - 1; + for(short int p = tx - 1; p >= 0; p--) { compe_cost += lines_x[p] * 2; } + wall_cost = 1; + for(int it2 = 1; it2 < 5; it2++) { + short int cx = block_info[i][it2][0]; + short int cy = block_info[i][it2][1]; + if(cx == tx && cy == ty) continue; + if(cy == ty && cx < tx) { + if(sx == 2 && sy == 3 && ty == 1) { + wall_cost = 4; + } + else { + wall_cost = 2; + } + } + } + line_info[tn][n_idx][LE] = compe_cost * wall_cost; + + // Map to top + compe_cost = 2; + compe_cost += lines_y[ty] - 1; + for(short int q = ty - 1; q >= 0; q--) { compe_cost += lines_y[q] * 2; } + wall_cost = 1; + for(int it2 = 1; it2 < 5; it2++) { + short int cx = block_info[i][it2][0]; + short int cy = block_info[i][it2][1]; + if(cx == tx && cy == ty) continue; + if(cx == tx && cy < ty) { + if(sx == 3 && sy == 2 && tx == 1) { + wall_cost = 4; + } + else { + wall_cost = 2; + } + } + } + line_info[tn][n_idx][TO] = compe_cost * wall_cost; + + // Map to right + compe_cost = 2; + compe_cost += lines_x[tx] - 1; + for(short int p = tx + 1; p < sx; p++) { compe_cost += lines_x[p] * 2; } + wall_cost = 1; + for(int it2 = 1; it2 < 5; it2++) { + short int cx = block_info[i][it2][0]; + short int cy = block_info[i][it2][1]; + if(cx == tx && cy == ty) continue; + if(cy == ty && cx > tx) { + if(sx == 2 && sy == 3 && ty == 1) { + wall_cost = 4; + } + else { + wall_cost = 2; + } + } + } + line_info[tn][n_idx][RI] = compe_cost * wall_cost; + + // Map to bottom + compe_cost = 2; + compe_cost += lines_y[ty] - 1; + for(short int q = ty + 1; q < sy; q++) { compe_cost += lines_y[q] * 2; } + wall_cost = 1; + for(int it2 = 1; it2 < 5; it2++) { + short int cx = block_info[i][it2][0]; + short int cy = block_info[i][it2][1]; + if(cx == tx && cy == ty) continue; + if(cx == tx && cy > ty) { + if(sx == 3 && sy == 2 && tx == 1) { + wall_cost = 4; + } + else { + wall_cost = 2; + } + } + } + line_info[tn][n_idx][BO] = compe_cost * wall_cost; + } + } + + /// Print line information /// + cout << "== Line information ==" << endl; + cout << "#Lines = " << line_num << endl; + for(int l = 1; l <= line_num; l++) { + short int block1 = line_info[l][0][0]; + short int block2 = line_info[l][1][0]; + cout << "Line#" << l << ": "; + cout << "Block#" << block1 << "("; + for(int i = 1; i < 5; i++) { + cout << (float)line_info[l][0][i] / 2; + if(i != 4) { cout << ", "; } + } + cout << "), "; + cout << "Block#" << block2 << "("; + for(int i = 1; i < 5; i++) { + cout << (float)line_info[l][1][i] / 2; + if(i != 4) { cout << ", "; } + } + cout << ")" << endl; + } + /// Print line information /// +} diff --git a/solver_python/io.hpp b/solver_python/io.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5ec103d897dddaa1f0bf66817c8d32b134bbb28d --- /dev/null +++ b/solver_python/io.hpp @@ -0,0 +1,17 @@ +#ifndef __IO_HPP__ +#define __IO_HPP__ + +#include +#include // for istringstream +#include +#include // for replace + +#include "param.hpp" + +using namespace std; + +void read_problem(const char *f_name, short int *W, short int *H, short int *blocks, short int *line_num, short int block_info[][5][3], short int line_info[][2][5]); +void extract_line_info(short int line_num, short int blocks, short int block_info[][5][3], short int line_info[][2][5]); + + +#endif /* __IO_HPP__ */ diff --git a/solver_python/main.cpp b/solver_python/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d16740595703c26588e85675891d30fe11ccf6b3 --- /dev/null +++ b/solver_python/main.cpp @@ -0,0 +1,105 @@ +#include +#include + +#include "param.hpp" +#include "io.hpp" +#include "solver.hpp" +#include "tools.hpp" + +using namespace std; + +void usage() { + cout << "Usage: ./sim.exe [--problem input-file] [--output output-file] [--seed seed-value]" << endl; + exit(-1); +} + +int main(int argc, char *argv[]) { + + char *p_filename = NULL; + char *out_filename = NULL; + uint32_t seed_v = 214; + + // Get options + struct option longopts[] = { + {"problem", required_argument, NULL, 'p'}, + {"output", required_argument, NULL, 'o'}, + {"seed", required_argument, NULL, 's'}, + {0, 0, 0, 0} + }; + int opt, optidx; + while((opt = getopt_long(argc, argv, "p:o:s:", longopts, &optidx)) != -1) { + switch(opt) { + case 'p': + p_filename = optarg; + break; + case 'o': + out_filename = optarg; + break; + case 's': + sscanf(optarg, "%u", &seed_v); + break; + default: + usage(); + } + } + + // Init seed value + uint32_t seed[3]; + srand(seed_v); + seed[0] = rand(); + seed[1] = rand(); + seed[2] = rand(); + + // W: Max width of a board (specified in a problem file) + // H: Max height of a board (specified in a problem file) + // blocks: # of blocks (specified in a problem file) + short int W, H, blocks, line_num; + // W_ext: Width of a current solution + // H_ext: Height of a current solution + short int W_ext, H_ext; + + // block data + short int block_info[MAX_BLOCKS+1][5][3]; + + // line data + short int line_info[MAX_LINES+1][2][5]; + + // An opt. result will be stored in the array + short int opt_result[MAX_CELLS]; + + // Check problem + read_problem(p_filename, &W, &H, &blocks, &line_num, block_info, line_info); + extract_line_info(line_num, blocks, block_info, line_info); + + // Solver body + int status = solver(seed, W, H, blocks, line_num, block_info, line_info, &W_ext, &H_ext, opt_result); + + // Check answer + if(status == 0) { + cout << "Fail re-routing" << endl; + } + else { + cout << "== Answer ==" << endl; + cout << "SIZE " << W_ext << "X" << H_ext << endl; + pair block_place_basis[MAX_BLOCKS+1]; + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = make_pair(block_info[i][0][0], block_info[i][0][1]); + } + show_result(line_num, blocks, W_ext, H_ext, opt_result, block_place_basis); + } + if(W_ext > W || H_ext > H) { + cout << "Fail satisfying constraint T_T" << endl; + } + else { + cout << "Satisfy constraint ^_^" << endl; + if(out_filename == NULL) return 0; + cout << "Output to " << out_filename << endl; + pair block_place_basis[MAX_BLOCKS+1]; + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = make_pair(block_info[i][0][0], block_info[i][0][1]); + } + output_to_file(out_filename, line_num, blocks, W_ext, H_ext, opt_result, block_place_basis); + } + + return 0; +} diff --git a/solver_python/main.py b/solver_python/main.py new file mode 100644 index 0000000000000000000000000000000000000000..99087401e1de06153bcda87b0d24dd9fbc5e75de --- /dev/null +++ b/solver_python/main.py @@ -0,0 +1,33 @@ +import numpy as np +from argparse import ArgumentParser +import mySolverModule + +def commandParsing(): + parser = ArgumentParser() + parser.add_argument('-p', '--problem', help='Problem file name', required=True) # Required + parser.add_argument('-s', '--seed', help='seed value') # Option + parser.add_argument('-o', '--output', help='Output file name') # Option + args = vars(parser.parse_args()) + return args + +def main(args): + seed_v = 214 + if args['seed'] is not None: seed_v = int(args['seed']) + seed = mySolverModule.seed_generator(seed_v) # ndarray + info = mySolverModule.check_problem(args['problem']) # extract info (block, line, ...) + + ret = mySolverModule.solver(seed, info['W'][0], info['H'][0], info['blocks'][0], info['line_num'][0], info['block_info'], info['line_info']) + + if ret['status'][0] == 0: print('Fail re-routing') + else: mySolverModule.show_result(ret['W_ext'][0], ret['H_ext'][0], info['blocks'][0], info['line_num'][0], ret['block_info'], ret['opt_result']) + + if ret['W_ext'][0] > info['W'][0] or ret['H_ext'][0] > info['H'][0]: + print('Fail satisfying constraint T_T') + else: + print('Satisfy constraint ^_^') + if args['output'] is not None: mySolverModule.output_to_file(args['output'], ret['W_ext'][0], ret['H_ext'][0], info['blocks'][0], info['line_num'][0], ret['block_info'], ret['opt_result']) + +if __name__ == '__main__': + + args = commandParsing() + main(args) diff --git a/solver_python/param.hpp b/solver_python/param.hpp new file mode 100644 index 0000000000000000000000000000000000000000..34b29d31a8f3849f3be8672b98e37d620d97d543 --- /dev/null +++ b/solver_python/param.hpp @@ -0,0 +1,45 @@ +#ifndef __PARAM_HPP__ +#define __PARAM_HPP__ + +#define MAX_BLOCKS 128 +#define MAX_LINES 256 +#define MAX_PATH 128 +#define MAX_CELLS 16384 // 128x128 +#define MAX_SIZE 128 +#define SLOT_MAX_SIZE 64 + + +#define ROUND_LIMIT 4096 //32768 // Max=65534(=2^16-2) +//#define PRINT_BOARD +//#define PRINT_SEARCH // for router debug + +#define PQ_BIT 16 +#define MAX_PQ 65536 + +#define PRIO_BIT 16 +#define DATA_BIT 16 +#define ELEM_BIT 32 // ELEM_BIT = PRIO_BIT + DATA_BIT + +#define DATA_MASK 65535 // 0000 FFFF +#define DATA_MAX 65535 // FFFF +#define PRIO_MAX 65535 // FFFF + +#define LE 1 +#define TO 2 +#define RI 3 +#define BO 4 + +#define SA_O 1000 +#define SA_I 100000 +#define TEMP_S 500 +#define TEMP_E 0.1 + +#define INTER_BLOCK_MARGIN 2 + +#define LOOP 50 +#define TRY_LIMIT 500 +#define NO_MOVE 10 + +#define LFSR_RAND_MAX 4294967295 + +#endif /* __PARAM_HPP__ */ diff --git a/solver_python/py_wrapper.cpp b/solver_python/py_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e99c5fe2a952a0d40fd56f9defef2c5272da995 --- /dev/null +++ b/solver_python/py_wrapper.cpp @@ -0,0 +1,407 @@ +/// py_wrapper.cpp /// + +// #include +#include "/usr/include/python3.5m/Python.h" +#include "/usr/include/python3.5m/numpy/arrayobject.h" +#include "/usr/include/python3.5m/numpy/arrayscalars.h" + +#include +#include +#include + +#include "param.hpp" +#include "io.hpp" +#include "solver.hpp" +#include "tools.hpp" + +using namespace std; + +#define N 50 + +// C++ function (Example) +void test_func(const char *f_name, int data[N], int *data_count) { + + int tmp, count = 0; + ifstream inputfile(f_name); + if(!inputfile) { + cout << f_name << ": Cannot open" << endl; + exit(1); + } + while(1) { + string line; + if(!getline(inputfile, line)) break; // from file + if(line.length() == 0) continue; + istringstream iss(line); + iss >> tmp; + data[count++] = tmp; + } + + cout << "#data = " << count << endl; + *data_count = count; +} + +// Wrapper +static PyObject* test_func_wrapper(PyObject* self, PyObject* args) { + + char *f_name = NULL; + int c_value; + + // PyObject (char*, int) + if(!PyArg_ParseTuple(args, "si", &f_name, &c_value)) { + return NULL; + } + + int data[N], data_count; + test_func(f_name, data, &data_count); + + // create dictionary + PyObject* dict = PyDict_New(); + + // create ndarray + int ndim = 1; + npy_intp *s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = N; + PyObject* out_list = PyArray_SimpleNew(ndim, s, NPY_INT32); // ndarray + free(s); + + for(npy_intp i = 0; i < N; i++) { + *(int*)PyArray_GETPTR1(out_list, i) = data[i] + c_value; + } + + PyObject* out_key = PyUnicode_FromString("out_key"); + + PyDict_SetItem(dict, out_key, out_list); + + // PyObject (dictionary) + return dict; +} + +static PyObject* seed_generator_wrapper(PyObject* self, PyObject* args) { + + uint32_t seed_v; + + // PyObject (unsigned int) + if(!PyArg_ParseTuple(args, "I", &seed_v)) { + return NULL; + } + + // create ndarray + int ndim = 1; + npy_intp *s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = 3; + PyObject* out_list = PyArray_SimpleNew(ndim, s, NPY_UINT32); + free(s); + + srand(seed_v); + *(uint32_t*)PyArray_GETPTR1(out_list, 0) = rand(); + *(uint32_t*)PyArray_GETPTR1(out_list, 1) = rand(); + *(uint32_t*)PyArray_GETPTR1(out_list, 2) = rand(); + + // PyObject (ndarray) + return out_list; +} + +static PyObject* check_problem_wrapper(PyObject* self, PyObject* args) { + + char *f_name = NULL; + + // PyObject (char*) + if(!PyArg_ParseTuple(args, "s", &f_name)) { + return NULL; + } + + // W: Max width of a board (specified in a problem file) + // H: Max height of a board (specified in a problem file) + // blocks: # of blocks (specified in a problem file) + short int W, H, blocks, line_num; + + // block data + short int block_info[MAX_BLOCKS+1][5][3]; + + // line data + short int line_info[MAX_LINES+1][2][5]; + + // Check problem + read_problem(f_name, &W, &H, &blocks, &line_num, block_info, line_info); + extract_line_info(line_num, blocks, block_info, line_info); + + // create dictionary + PyObject* dict = PyDict_New(); + + // W, H, blocks, line_num // + PyObject* W_key = PyUnicode_FromString("W"); + PyObject* H_key = PyUnicode_FromString("H"); + PyObject* blocks_key = PyUnicode_FromString("blocks"); + PyObject* line_key = PyUnicode_FromString("line_num"); + + int ndim = 1; + npy_intp *s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = 1; + PyObject* W_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + PyObject* H_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + PyObject* blocks_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + PyObject* line_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + free(s); + + *(short int*)PyArray_GETPTR1(W_list, 0) = W; + *(short int*)PyArray_GETPTR1(H_list, 0) = H; + *(short int*)PyArray_GETPTR1(blocks_list, 0) = blocks; + *(short int*)PyArray_GETPTR1(line_list, 0) = line_num; + + PyDict_SetItem(dict, W_key, W_list); + PyDict_SetItem(dict, H_key, H_list); + PyDict_SetItem(dict, blocks_key, blocks_list); + PyDict_SetItem(dict, line_key, line_list); + + // block_info // + PyObject* block_info_key = PyUnicode_FromString("block_info"); + + ndim = 3; + s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = MAX_BLOCKS+1; + s[1] = 5; + s[2] = 3; + PyObject* block_info_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + free(s); + + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + for(npy_intp j = 0; j < 5; j++) { + for(npy_intp k = 0; k < 3; k++) { + *(short int*)PyArray_GETPTR3(block_info_list, i, j, k) = block_info[i][j][k]; + } + } + } + + PyDict_SetItem(dict, block_info_key, block_info_list); + + // line_info // + PyObject* line_info_key = PyUnicode_FromString("line_info"); + + ndim = 3; + s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = MAX_LINES+1; + s[1] = 2; + s[2] = 5; + PyObject* line_info_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + free(s); + + for(npy_intp i = 0; i < MAX_LINES+1; i++) { + for(npy_intp j = 0; j < 2; j++) { + for(npy_intp k = 0; k < 5; k++) { + *(short int*)PyArray_GETPTR3(line_info_list, i, j, k) = line_info[i][j][k]; + } + } + } + + PyDict_SetItem(dict, line_info_key, line_info_list); + + // PyObject (dictionary) + return dict; +} + +static PyObject* solver_wrapper(PyObject* self, PyObject* args) { + + uint32_t seed[3]; + short int W, H, blocks, line_num; + short int block_info[MAX_BLOCKS+1][5][3]; + short int line_info[MAX_LINES+1][2][5]; + + PyObject* a_seed; + PyObject* a_block_info; + PyObject* a_line_info; + + // PyObject (ndarray, short int, short int, short int, short int, ndarray, ndarray) + if(!PyArg_ParseTuple(args, "O!hhhhO!O!", &PyArray_Type, &a_seed, &W, &H, &blocks, &line_num, &PyArray_Type, &a_block_info, &PyArray_Type, &a_line_info)) { + return NULL; + } + + seed[0] = *(uint32_t*)PyArray_GETPTR1(a_seed, 0); + seed[1] = *(uint32_t*)PyArray_GETPTR1(a_seed, 1); + seed[2] = *(uint32_t*)PyArray_GETPTR1(a_seed, 2); + + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + for(npy_intp j = 0; j < 5; j++) { + for(npy_intp k = 0; k < 3; k++) { + block_info[i][j][k] = *(short int*)PyArray_GETPTR3(a_block_info, i, j, k); + } + } + } + + for(npy_intp i = 0; i < MAX_LINES+1; i++) { + for(npy_intp j = 0; j < 2; j++) { + for(npy_intp k = 0; k < 5; k++) { + line_info[i][j][k] = *(short int*)PyArray_GETPTR3(a_line_info, i, j, k); + } + } + } + + // W_ext: Width of a current solution + // H_ext: Height of a current solution + short int W_ext, H_ext; + + // An opt. result will be stored in the array + short int opt_result[MAX_CELLS]; + + int status = solver(seed, W, H, blocks, line_num, block_info, line_info, &W_ext, &H_ext, opt_result); + + // create dictionary + PyObject* dict = PyDict_New(); + + // status // + PyObject* status_key = PyUnicode_FromString("status"); + PyObject* W_ext_key = PyUnicode_FromString("W_ext"); + PyObject* H_ext_key = PyUnicode_FromString("H_ext"); + + int ndim = 1; + npy_intp *s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = 1; + PyObject* status_list = PyArray_SimpleNew(ndim, s, NPY_INT32); // ndarray + PyObject* W_ext_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + PyObject* H_ext_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + free(s); + + *(int*)PyArray_GETPTR1(status_list, 0) = status; + *(short int*)PyArray_GETPTR1(W_ext_list, 0) = W_ext; + *(short int*)PyArray_GETPTR1(H_ext_list, 0) = H_ext; + + PyDict_SetItem(dict, status_key, status_list); + PyDict_SetItem(dict, W_ext_key, W_ext_list); + PyDict_SetItem(dict, H_ext_key, H_ext_list); + + // block_info // + PyObject* block_info_key = PyUnicode_FromString("block_info"); + + ndim = 3; + s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = MAX_BLOCKS+1; + s[1] = 5; + s[2] = 3; + PyObject* block_info_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + free(s); + + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + for(npy_intp j = 0; j < 5; j++) { + for(npy_intp k = 0; k < 3; k++) { + *(short int*)PyArray_GETPTR3(block_info_list, i, j, k) = block_info[i][j][k]; + } + } + } + + PyDict_SetItem(dict, block_info_key, block_info_list); + + // opt_result // + PyObject* opt_result_key = PyUnicode_FromString("opt_result"); + + ndim = 1; + s = (npy_intp*)malloc(ndim * sizeof(npy_intp)); + s[0] = MAX_CELLS; + PyObject* opt_result_list = PyArray_SimpleNew(ndim, s, NPY_INT16); // ndarray + free(s); + + for(npy_intp i = 0; i < MAX_CELLS; i++) { + *(short int*)PyArray_GETPTR1(opt_result_list, i) = opt_result[i]; + } + + PyDict_SetItem(dict, opt_result_key, opt_result_list); + + // PyObject (dictionary) + return dict; +} + +static PyObject* show_result_wrapper(PyObject* self, PyObject* args) { + + short int W_ext, H_ext, blocks, line_num; + short int block_info[MAX_BLOCKS+1][5][3]; + short int opt_result[MAX_CELLS]; + + PyObject* a_block_info; + PyObject* a_opt_result; + + // PyObject (short int, short int, short int, short int, ndarray, ndarray) + if(!PyArg_ParseTuple(args, "hhhhO!O!", &W_ext, &H_ext, &blocks, &line_num, &PyArray_Type, &a_block_info, &PyArray_Type, &a_opt_result)) { + return NULL; + } + + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + for(npy_intp j = 0; j < 5; j++) { + for(npy_intp k = 0; k < 3; k++) { + block_info[i][j][k] = *(short int*)PyArray_GETPTR3(a_block_info, i, j, k); + } + } + } + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + opt_result[i] = *(short int*)PyArray_GETPTR1(a_opt_result, i); + } + + cout << "== Answer ==" << endl; + cout << "SIZE " << W_ext << "X" << H_ext << endl; + pair block_place_basis[MAX_BLOCKS+1]; + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = make_pair(block_info[i][0][0], block_info[i][0][1]); + } + show_result(line_num, blocks, W_ext, H_ext, opt_result, block_place_basis); + + return Py_None; +} + +static PyObject* output_to_file_wrapper(PyObject* self, PyObject* args) { + + char *f_name = NULL; + short int W_ext, H_ext, blocks, line_num; + short int block_info[MAX_BLOCKS+1][5][3]; + short int opt_result[MAX_CELLS]; + + PyObject* a_block_info; + PyObject* a_opt_result; + + // PyObject (char* short int, short int, short int, short int, ndarray, ndarray) + if(!PyArg_ParseTuple(args, "shhhhO!O!", &f_name, &W_ext, &H_ext, &blocks, &line_num, &PyArray_Type, &a_block_info, &PyArray_Type, &a_opt_result)) { + return NULL; + } + + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + for(npy_intp j = 0; j < 5; j++) { + for(npy_intp k = 0; k < 3; k++) { + block_info[i][j][k] = *(short int*)PyArray_GETPTR3(a_block_info, i, j, k); + } + } + } + for(npy_intp i = 0; i < MAX_BLOCKS+1; i++) { + opt_result[i] = *(short int*)PyArray_GETPTR1(a_opt_result, i); + } + + cout << "Output to " << f_name << endl; + pair block_place_basis[MAX_BLOCKS+1]; + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = make_pair(block_info[i][0][0], block_info[i][0][1]); + } + output_to_file(f_name, line_num, blocks, W_ext, H_ext, opt_result, block_place_basis); + + return Py_None; +} + +// Module definition +static PyMethodDef mySolverMethods[] = { + {"test_func", test_func_wrapper, METH_VARARGS, "test function"}, + {"seed_generator", seed_generator_wrapper, METH_VARARGS, "generate seed values"}, + {"check_problem", check_problem_wrapper, METH_VARARGS, "read problem"}, + {"solver", solver_wrapper, METH_VARARGS, "solver"}, + {"show_result", show_result_wrapper, METH_VARARGS, "show result"}, + {"output_to_file", output_to_file_wrapper, METH_VARARGS, "output result to file"}, + {NULL} +}; + +static struct PyModuleDef mySolverModule = { + PyModuleDef_HEAD_INIT, + "mySolverModule", + "Python3 C API Module(test)", + -1, + mySolverMethods +}; + +// Init. myModule +PyMODINIT_FUNC PyInit_mySolverModule(void) { + import_array(); + return PyModule_Create(&mySolverModule); +} + diff --git a/solver_python/sample_A.txt b/solver_python/sample_A.txt new file mode 100644 index 0000000000000000000000000000000000000000..16f54de4cebe6451f4e74159a1b31cbec0b2e7c4 --- /dev/null +++ b/solver_python/sample_A.txt @@ -0,0 +1,19 @@ +SIZE 8X10 +1, 1, 1, 2, 2, 2, 2, 0 +0, 0, 4, 0, 0, 0, 2, 2 +8, 8, 4, 4, 4, 0, 4, 2 +7, 8, 0, 0, 4, 4, 4, 2 +7, 6, 0, 0, 0, 0, 2, 2 +0, 6, 6, 6, 5, 11, 0, 0 +10, 10, 10, 6, 5, 11, 0, 0 +0, 9, 5, 5, 5, 0, 0, 3 +3, 9, 3, 3, 3, 3, 3, 3 +3, 3, 3, 0, 0, 0, 0, 0 +BLOCK#1 @(0,0) +BLOCK#2 @(0,3) +BLOCK#3 @(0,6) +BLOCK#4 @(2,0) +BLOCK#5 @(5,6) +BLOCK#6 @(4,4) +BLOCK#7 @(1,6) +BLOCK#8 @(4,1) diff --git a/solver_python/sample_Q.txt b/solver_python/sample_Q.txt new file mode 100644 index 0000000000000000000000000000000000000000..f99ce862c4eaf2a200d2365582736cf36ccc661a --- /dev/null +++ b/solver_python/sample_Q.txt @@ -0,0 +1,37 @@ +SIZE 10X10 +BLOCK_NUM 8 + +BLOCK#1 1X4 +1 ++ +8 +7 + +BLOCK#2 3X2 +0,8,0 +7,6,+ + +BLOCK#3 2X3 +10,0 + +,0 + 3,9 + +BLOCK#4 2X2 +1,2 +4,+ + +BLOCK#5 3X2 +11,+,+ + 0,0,3 + +BLOCK#6 3X2 +0, +,2 +5,11,0 + +BLOCK#7 3X2 +0,10,6 +9, 5,0 + +BLOCK#8 3X2 ++,+,0 +0,+,4 \ No newline at end of file diff --git a/solver_python/setup.py b/solver_python/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..830181cf6fe429644be684c9fc38dea55ec9f166 --- /dev/null +++ b/solver_python/setup.py @@ -0,0 +1,4 @@ +from distutils.core import setup, Extension + +setup(name = 'mySolverModule', version = '1.0.0', ext_modules = [Extension('mySolverModule', sources=['py_wrapper.cpp','io.cpp','solver.cpp','tools.cpp'], extra_compile_args=['-O3', '-w'])]) + diff --git a/solver_python/solver.cpp b/solver_python/solver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9eb718a868e7f13a82beaa118185268c3e4f7e2f --- /dev/null +++ b/solver_python/solver.cpp @@ -0,0 +1,1023 @@ +#include "solver.hpp" + +static uint32_t lfsr, lfsr_x, lfsr_y; + +int solver(uint32_t seed[3], short int W, short int H, short int blocks, short int line_num, short int block_info[][5][3], short int line_info[][2][5], short int *pwi, short int *phi, short int opt_result[]) { + + lfsr_random_init(seed[0], seed[1], seed[2]); + + // block positions on slot matrix + pair block_place_global[MAX_BLOCKS+1]; + + while(1) { + global_placement(W, H, line_num, blocks, block_info, line_info, block_place_global); + if(local_placement_with_routing_1(line_num, blocks, pwi, phi, block_info, block_place_global, opt_result)) break; + } + bool result = local_placement_with_routing_2(line_num, blocks, pwi, phi, block_info, opt_result); + + if(result) return 1; + return 0; +} + +void lfsr_random_init(uint32_t seed, uint32_t seed_x, uint32_t seed_y) { + lfsr = seed; + lfsr_x = seed_x; + lfsr_y = seed_y; +} + +uint32_t lfsr_random() { + bool b_32 = false, b_22 = false, b_2 = false, b_1 = false; + if((lfsr >> 0) % 2 == 1) b_32 = true; + if((lfsr >> 10) % 2 == 1) b_22 = true; + if((lfsr >> 30) % 2 == 1) b_2 = true; + if((lfsr >> 31) % 2 == 1) b_1 = true; + bool new_bit = b_32 ^ b_22 ^ b_2 ^ b_1; + lfsr >>= 1; + if(new_bit) lfsr |= 0x80000000; + return lfsr; +} +uint32_t lfsr_x_random() { + bool b_32 = false, b_22 = false, b_2 = false, b_1 = false; + if((lfsr_x >> 0) % 2 == 1) b_32 = true; + if((lfsr_x >> 10) % 2 == 1) b_22 = true; + if((lfsr_x >> 30) % 2 == 1) b_2 = true; + if((lfsr_x >> 31) % 2 == 1) b_1 = true; + bool new_bit = b_32 ^ b_22 ^ b_2 ^ b_1; + lfsr_x >>= 1; + if(new_bit) lfsr_x |= 0x80000000; + return lfsr_x; +} +uint32_t lfsr_y_random() { + bool b_32 = false, b_22 = false, b_2 = false, b_1 = false; + if((lfsr_y >> 0) % 2 == 1) b_32 = true; + if((lfsr_y >> 10) % 2 == 1) b_22 = true; + if((lfsr_y >> 30) % 2 == 1) b_2 = true; + if((lfsr_y >> 31) % 2 == 1) b_1 = true; + bool new_bit = b_32 ^ b_22 ^ b_2 ^ b_1; + lfsr_y >>= 1; + if(new_bit) lfsr_y |= 0x80000000; + return lfsr_y; +} + +float calcPlaceCost(short int line_num, short int line_info[][2][5], pair block_place_global[]) { + + short int block1, block2; // block idx + short int x1, y1; // 1st block + short int x2, y2; // 2nd block + short int delta_x, delta_y; + // delta_x > 0: 1st block is located in the East of 2nd block + // delta_x < 0: 1st block is located in the West of 2nd block + // delta_y > 0: 1st block is located in the South of 2nd block + // delta_y < 0: 1st block is located in the North of 2nd block + short int dist_x, dist_y; // distance between 2 blocks + float dir_x1, dir_x2; // X-direction from 1st block to 2nd block and ... + float dir_y1, dir_y2; // Y-direction from 1st block to 2nd block and ... + + float cost = 0.0; + for(int l = 1; l <= line_num; l++) { // Calc cost + block1 = line_info[l][0][0]; // 1st block including line#L + block2 = line_info[l][1][0]; // 2nd block including line#L + x1 = block_place_global[block1].first; + y1 = block_place_global[block1].second; + x2 = block_place_global[block2].first; + y2 = block_place_global[block2].second; + delta_x = x1 - x2; + delta_y = y1 - y2; + dist_x = abs(delta_x); + dist_y = abs(delta_y); + + dir_x1 = 0.0; + dir_x2 = 0.0; + if(delta_x > 0) { + dir_x1 = (float)line_info[l][0][1] / 2; + dir_x2 = (float)line_info[l][1][3] / 2; + } + else if(delta_x < 0) { + dir_x1 = (float)line_info[l][0][3] / 2; + dir_x2 = (float)line_info[l][1][1] / 2; + } + dir_y1 = 0.0; + dir_y2 = 0.0; + if(delta_y > 0) { + dir_y1 = (float)line_info[l][0][2] / 2; + dir_y2 = (float)line_info[l][1][4] / 2; + } + else if(delta_y < 0) { + dir_y1 = (float)line_info[l][0][4] / 2; + dir_y2 = (float)line_info[l][1][2] / 2; + } + cost += dist_x * dir_x1 * dir_x2 + dist_y * dir_y1 * dir_y2; + } + + return cost; +} + +void global_placement(short int W, short int H, short int line_num, short int blocks, short int block_info[][5][3], short int line_info[][2][5], pair block_place_global[]) { + + cout << "== Global placement ==" << endl; + short int sx_sum = 0, sy_sum = 0; + for(int i = 1; i <= blocks; i++) { + sx_sum += block_info[i][0][0]; // block size (x) + sy_sum += block_info[i][0][1]; // block size (y) + } + // define #slots + short int max_x = W * blocks / sx_sum - 1; + short int max_y = H * blocks / sy_sum - 1; + while(((max_x + 1) * (max_y + 1)) < blocks) { + max_x += 1; + max_y += 1; + } + cout << "#Slots for X-axis: " << max_x + 1 << endl; + cout << "#Slots for Y-axis: " << max_y + 1 << endl; + + // init. placement on global slot + short int global_slot[SLOT_MAX_SIZE][SLOT_MAX_SIZE]; + short int i = 1; + for(short int q = 0; q <= max_y; q++) { + for(short int p = 0; p <= max_x; p++) { + if(i <= blocks) { + block_place_global[i] = make_pair(p, q); + global_slot[q][p] = i; + //cout << "Block#" << i << ": (" << block_place_global[i].first << ", " << block_place_global[i].second << ")" << endl; + i++; + } + else { + global_slot[q][p] = 0; + } + } + } + + // cost calculation (may be inefficient) + float cost = calcPlaceCost(line_num, line_info, block_place_global); + cout << "Cost = " << cost << " -> "; + + // SA setup + float temperature = TEMP_S; + float delta = powf(((float)(TEMP_E)/(float)(TEMP_S)), (1./(float)(SA_O))); + //cout << "delta = " << delta << endl; + + // SA + for(int counter = 0; counter < SA_O; counter++) { + temperature *= delta; // Update temperature + + // trgt_i, trgt_j: moved block idx (trgt_j == 0, no block is placed on slot(j_x,j_y)) + // i_x, i_y, j_x, j_y + for(int counter_in = 0; counter_in < SA_I; counter_in++) { + short int trgt_i = lfsr_random() % blocks + 1; + short int i_x = block_place_global[trgt_i].first; + short int i_y = block_place_global[trgt_i].second; + short int j_x = lfsr_x_random() % SLOT_MAX_SIZE; + short int j_y = lfsr_y_random() % SLOT_MAX_SIZE; + if(j_x > max_x || j_y > max_y) continue; + short int trgt_j = global_slot[j_y][j_x]; // slot -> block + + block_place_global[trgt_i].first = j_x; + block_place_global[trgt_i].second = j_y; + global_slot[j_y][j_x] = trgt_i; + block_place_global[trgt_j].first = i_x; + block_place_global[trgt_j].second = i_y; + global_slot[i_y][i_x] = trgt_j; + + float new_cost = calcPlaceCost(line_num, line_info, block_place_global); + + if(new_cost > cost && (float)lfsr_random()/LFSR_RAND_MAX > expf(-(new_cost-cost)/temperature)) { + block_place_global[trgt_i].first = i_x; + block_place_global[trgt_i].second = i_y; + global_slot[i_y][i_x] = trgt_i; + block_place_global[trgt_j].first = j_x; + block_place_global[trgt_j].second = j_y; + global_slot[j_y][j_x] = trgt_j; + } + else if(new_cost != cost) { + cost = new_cost; + } + } + } + + //for(i = 1; i <= blocks; i++) { // final placement on global slot + // cout << "Block#" << i << ": (" << block_place_global[i].first << ", " << block_place_global[i].second << ")" << endl; + //} + cout << cost << endl; + + //for(q = 0; q <= max_y; q++) { + // for(p = 0; p <= max_x; p++) { + // cout << global_slot[q][p] << " "; + // } + // cout << endl; + //} +} + +pair add_pair(pair x, pair y) { + return make_pair(x.first+y.first, x.second+y.second); +} + +pair sub_pair(pair x, pair y) { + return make_pair(x.first-y.first, x.second-y.second); +} + +bool local_placement_with_routing_1(short int line_num, short int blocks, short int *pwi, short int *phi, short int block_info[][5][3], pair block_place_global[], short int opt_result[]) { + + short int wi, hi; // board size (w, h) + + // size of each slot (w, h) + short int slot_w[SLOT_MAX_SIZE], slot_h[SLOT_MAX_SIZE]; + // basic position of each slot (x, y) + short int slot_w_t[SLOT_MAX_SIZE], slot_h_t[SLOT_MAX_SIZE]; + + short int block_place_slack[MAX_BLOCKS+1][2]; + pair block_place_basis[MAX_BLOCKS+1]; + pair block_place_delta[MAX_BLOCKS+1]; + pair block_place_opt[MAX_BLOCKS+1]; + + short int board_str[MAX_CELLS]; + + // load a placement result + short int min_x = SLOT_MAX_SIZE, min_y = SLOT_MAX_SIZE, max_x = 0, max_y = 0; + for(int i = 1; i <= blocks; i++) { + short int p = block_place_global[i].first; + short int q = block_place_global[i].second; + if(p < min_x) { min_x = p; } + if(q < min_y) { min_y = q; } + if(p > max_x) { max_x = p; } + if(q > max_y) { max_y = q; } + } + for(short int p = min_x; p <= max_x; p++) { + slot_w[p] = 0; + } + for(short int q = min_y; q <= max_y; q++) { + slot_h[q] = 0; + } + for(int i = 1; i <= blocks; i++) { + short int sx = block_info[i][0][0]; + short int sy = block_info[i][0][1]; + short int p = block_place_global[i].first; + short int q = block_place_global[i].second; + if(sx > slot_w[p]) { slot_w[p] = sx; } + if(sy > slot_h[q]) { slot_h[q] = sy; } + } + wi = INTER_BLOCK_MARGIN; + for(short int p = min_x; p <= max_x; p++) { + slot_w_t[p] = wi; + wi += slot_w[p] + INTER_BLOCK_MARGIN; + } + hi = INTER_BLOCK_MARGIN; + for(short int q = min_y; q <= max_y; q++) { + slot_h_t[q] = hi; + hi += slot_h[q] + INTER_BLOCK_MARGIN; + } + + cout << "== Local placement with routing (1) ==" << endl; + cout << "Board size = " << wi << "X" << hi << endl; + + // calculate slack for each block + for(int i = 1; i <= blocks; i++) { + short int sx = block_info[i][0][0]; + short int sy = block_info[i][0][1]; + short int p = block_place_global[i].first; + short int q = block_place_global[i].second; + block_place_basis[i] = make_pair(slot_w_t[p], slot_h_t[q]); + block_place_slack[i][0] = slot_w[p] - sx; + block_place_slack[i][1] = slot_h[q] - sy; + //cout << "Block#" << i << ": (" << block_place_basis[i].first << "," << block_place_basis[i].second << ")" << endl; + //cout << "Slack(x)=" << block_place_slack[i][0] << ", Slack(y)=" << block_place_slack[i][1] << endl; + } + + bool find_route = false; + int min_status = wi * hi + 1; + for(int counter = 0; counter < LOOP; counter++) { + cout << "."; fflush(stdout); + for(int s = 0; s < MAX_CELLS; s++) { + board_str[s] = 0; + } + for(int i = 1; i <= blocks; i++) { + short int x = block_place_basis[i].first; + short int y = block_place_basis[i].second; + short int dx = lfsr_x_random() % (block_place_slack[i][0] + 1); + short int dy = lfsr_y_random() % (block_place_slack[i][1] + 1); + block_place_delta[i] = make_pair(dx, dy); + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + if(tn < 0) break; + short int p = x + dx + tx; + short int q = y + dy + ty; + short int idx = q * MAX_SIZE + p; + if(tn > 0) { board_str[idx] = tn; } + else { board_str[idx] = -1; } + } + } + + int status = router(wi, hi, line_num, board_str); // routing + + if(status >= 0 && status < min_status) { + min_status = status; + find_route = true; + for(int i = 1; i <= blocks; i++) { + block_place_opt[i] = add_pair(block_place_basis[i], block_place_delta[i]); + } + for(int s = 0; s < MAX_CELLS; s++) { + opt_result[s] = board_str[s]; + } + } + } + cout << endl; + + if(!find_route) return false; + + // Update + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = block_place_opt[i]; + } + + /// print for debug /// + cout << "Min-wire status: " << min_status << endl; + show_result(line_num, blocks, wi, hi, opt_result, block_place_basis); + /// print for debug /// + + //cout << "== Local placement with routing (1+) ==" << endl; + bool remove_flag; + short int deleted_line_w = 0, deleted_line_h = 0; + for(short int q = hi - 1; q >= 0; q--) { + remove_flag = true; + for(short int p = 0; p < wi; p++) { + short int idx = q * MAX_SIZE + p; + if(opt_result[idx] != 0) { + remove_flag = false; + break; + } + } + if(remove_flag) { + for(int i = 1; i <= blocks; i++) { + if(block_place_basis[i].second > q) { block_place_basis[i].second -= 1; } + } + deleted_line_h++; + } + } + for(short int p = wi - 1; p >= 0; p--) { + remove_flag = true; + for(short int q = 0; q < hi; q++) { + short int idx = q * MAX_SIZE + p; + if(opt_result[idx] != 0) { + remove_flag = false; + break; + } + } + if(remove_flag) { + for(int i = 1; i <= blocks; i++) { + if(block_place_basis[i].first > p) { block_place_basis[i].first -= 1; } + } + deleted_line_w++; + } + } + hi -= deleted_line_h; + wi -= deleted_line_w; + + for(int s = 0; s < MAX_CELLS; s++) { + board_str[s] = 0; + } + for(int i = 1; i <= blocks; i++) { + short int x = block_place_basis[i].first; + short int y = block_place_basis[i].second; + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + if(tn < 0) break; + short int p = x + tx; + short int q = y + ty; + short int idx = q * MAX_SIZE + p; + if(tn > 0) { board_str[idx] = tn; } + else { board_str[idx] = -1; } + } + } + + int counter = 0; + while(router(wi, hi, line_num, board_str) < 0) { + if(counter++ >= LOOP) return false; + } + for(int s = 0; s < MAX_CELLS; s++) { + opt_result[s] = board_str[s]; + } + + for(int i = 1; i <= blocks; i++) { + block_info[i][0][0] = block_place_basis[i].first; + block_info[i][0][1] = block_place_basis[i].second; + } + *pwi = wi; + *phi = hi; + + return true; +} + +bool local_placement_with_routing_2(short int line_num, short int blocks, short int *pwi, short int *phi, short int block_info[][5][3], short int opt_result[]) { + + short int wi = *pwi, hi = *phi; + + short int block_place_slack[MAX_BLOCKS+1][2]; + pair block_place_basis[MAX_BLOCKS+1]; + pair block_place_delta[MAX_BLOCKS+1]; + pair block_place_opt[MAX_BLOCKS+1]; + + short int board_str[MAX_CELLS]; + + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = make_pair(block_info[i][0][0], block_info[i][0][1]); + } + + cout << "== Local placement with routing (2) ==" << endl; + int direction = 0; // 0: X, 1: Y + int try_count = 1; + int no_update = 0; + + if(hi > wi) direction = 1; + while(try_count <= TRY_LIMIT) { + cout << "Phase " << try_count << ": direction: "; + switch(direction) { + case 0: cout << "X" << endl; break; + case 1: cout << "Y" << endl; break; + } + cout << "Board size = " << wi << "X" << hi << endl; + + // calculate slack for each block + for(int t = 1; t <= blocks; t++) { + block_place_slack[t][0] = 0; + block_place_slack[t][1] = 0; + for(int s = 0; s < MAX_CELLS; s++) { + board_str[s] = 0; + } + for(int i = 1; i <= blocks; i++) { + if(i == t) continue; + short int x = block_place_basis[i].first; + short int y = block_place_basis[i].second; + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + if(tn < 0) break; + short int p = x + tx; + short int q = y + ty; + short int idx = q * MAX_SIZE + p; + if(tn > 0) { board_str[idx] = tn; } + else { board_str[idx] = -1; } + } + } + bool move_x = true, move_y = true; + while(1) { // X direction + short int x = block_place_basis[t].first; + short int y = block_place_basis[t].second; + for(int it = 1; it < 5; it++) { + short int tx = block_info[t][it][0]; + short int ty = block_info[t][it][1]; + short int tn = block_info[t][it][2]; + if(tn < 0) break; + short int p = x + tx - (block_place_slack[t][0]+1); + short int q = y + ty; + short int idx = q * MAX_SIZE + p; + if(p < 0 || board_str[idx] != 0) { + move_x = false; + break; + } + } + if(move_x) { + if(++block_place_slack[t][0] >= 9) break; + } + else { + break; + } + } + while(1) { // Y direction + short int x = block_place_basis[t].first; + short int y = block_place_basis[t].second; + for(int it = 1; it < 5; it++) { + short int tx = block_info[t][it][0]; + short int ty = block_info[t][it][1]; + short int tn = block_info[t][it][2]; + if(tn < 0) break; + short int p = x + tx; + short int q = y + ty - (block_place_slack[t][1]+1); + short int idx = q * MAX_SIZE + p; + if(q < 0 || board_str[idx] != 0) { + move_y = false; + break; + } + } + if(move_y) { + if(++block_place_slack[t][1] >= 9) break; + } + else { + break; + } + } + //cout << "Block#" << t << ": (" << block_place_basis[t].first << "," << block_place_basis[t].second << ")" << endl; + //cout << "Slack(x)=" << block_place_slack[t][0] << ", Slack(y)=" << block_place_slack[t][1] << endl; + } + + no_update++; + bool find_route = false; + int d_sum_max = 0; + for(int counter = 0; counter < LOOP; counter++) { + cout << "."; fflush(stdout); + for(int s = 0; s < MAX_CELLS; s++) { + board_str[s] = 0; + } + int d_sum = 0; + for(int i = 1; i <= blocks; i++) { + short int x = block_place_basis[i].first; + short int y = block_place_basis[i].second; + short int dx = 0; + short int dy = 0; + switch(direction) { + case 0: dx = lfsr_x_random() % (block_place_slack[i][0] + 1); break; + case 1: dy = lfsr_y_random() % (block_place_slack[i][1] + 1); break; + } + if(lfsr_random() % 16 >= 2) { + dx = 0; + dy = 0; + } + block_place_delta[i] = make_pair(dx, dy); + d_sum += dx + dy; + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + if(tn < 0) break; + short int p = x - dx + tx; + short int q = y - dy + ty; + short int idx = q * MAX_SIZE + p; + if(tn > 0) { board_str[idx] = tn; } + else{ board_str[idx] = -1; } + } + } + + int status = router(wi, hi, line_num, board_str); + + if(status >= 0 && d_sum > d_sum_max) { + d_sum_max = d_sum; + find_route = true; + for(int i = 1; i <= blocks; i++) { + block_place_opt[i] = sub_pair(block_place_basis[i], block_place_delta[i]); + } + for(int s = 0; s < MAX_CELLS; s++) { + opt_result[s] = board_str[s]; + } + } + } + cout << endl; + + if(find_route) { + + no_update = 0; // reset + + // Update + for(int i = 1; i <= blocks; i++) { + block_place_basis[i] = block_place_opt[i]; + } + + /// print for debug /// + cout << "Max dSum: " << d_sum_max << endl; + show_result(line_num, blocks, wi, hi, opt_result, block_place_basis); + /// print for debug /// + + bool remove_flag; + short int deleted_line_w = 0, deleted_line_h = 0; + for(short int q = hi - 1; q >= 0; q--) { + remove_flag = true; + for(short int p = 0; p < wi; p++) { + short int idx = q * MAX_SIZE + p; + if(opt_result[idx] != 0) { + remove_flag = false; + break; + } + } + if(remove_flag) { + for(int i = 1; i <= blocks; i++) { + if(block_place_basis[i].second > q) { block_place_basis[i].second -= 1; } + } + deleted_line_h++; + } + } + for(short int p = wi - 1; p >= 0; p--) { + remove_flag = true; + for(short int q = 0; q < hi; q++) { + short int idx = q * MAX_SIZE + p; + if(opt_result[idx] != 0) { + remove_flag = false; + break; + } + } + if(remove_flag) { + for(int i = 1; i <= blocks; i++) { + if(block_place_basis[i].first > p) { block_place_basis[i].first -= 1; } + } + deleted_line_w++; + } + } + hi -= deleted_line_h; + wi -= deleted_line_w; + + for(int s = 0; s < MAX_CELLS; s++) { + board_str[s] = 0; + } + for(int i = 1; i <= blocks; i++) { + short int x = block_place_basis[i].first; + short int y = block_place_basis[i].second; + for(int it = 1; it < 5; it++) { + short int tx = block_info[i][it][0]; + short int ty = block_info[i][it][1]; + short int tn = block_info[i][it][2]; + if(tn < 0) break; + short int p = x + tx; + short int q = y + ty; + short int idx = q * MAX_SIZE + p; + if(tn > 0) { board_str[idx] = tn; } + else { board_str[idx] = -1; } + } + } + + int counter = 0; + while(router(wi, hi, line_num, board_str) < 0) { + if(counter++ >= LOOP) return false; + } + for(int s = 0; s < MAX_CELLS; s++) { + opt_result[s] = board_str[s]; + } + } + + if(no_update >= NO_MOVE) break; + + try_count++; + switch(direction) { + case 0: direction = 1; break; + case 1: direction = 0; break; + } + } + cout << "#Tries: " << try_count << endl; + *pwi = wi; + *phi = hi; + for(int i = 1; i <= blocks; i++) { + block_info[i][0][0] = block_place_basis[i].first; + block_info[i][0][1] = block_place_basis[i].second; + } + + return true; +} + + + + + + + +unsigned short int new_weight(unsigned short int x) { + unsigned short int y = (x & 0x00FF) + 1; + return y; +} + +// DATA_BIT: bit length of cell idx +// PRIO_BIT: bit length of cost(priority) +int router(short int size_x, short int size_y, short int line_num, short int board_str[MAX_CELLS]) { + + if(line_num == 0) return 0; + + short int terminals[MAX_LINES][2]; + short int paths_size[MAX_LINES]; + unsigned short int paths[MAX_LINES][MAX_PATH]; + bool adjacents[MAX_LINES]; + + unsigned short int weights[MAX_CELLS]; + + SET_LOOP_1: + for(int i = 0; i < line_num; i++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + terminals[i][0] = -1; + terminals[i][1] = -1; + paths_size[i] = 0; + adjacents[i] = false; + } + SET_LOOP_2: + for(short int j = 0; j < MAX_CELLS; j++) { + short int y = j / MAX_SIZE; + short int x = j - MAX_SIZE * y; + if(x >= size_x || y >= size_y) continue; + short int num = board_str[j]; + if(num > 0) { + if(terminals[num-1][0] < 0) { terminals[num-1][0] = j; } + else if(terminals[num-1][1] < 0) { terminals[num-1][1] = j; } + else { return -2; } + weights[j] = PRIO_MAX; + } + else if(num < 0) { + weights[j] = PRIO_MAX; + } + else { + weights[j] = 1; + } + } + +#ifdef PRINT_BOARD + cout << "== Print board ==" << endl; + for(short int y = 0; y < size_y; y++) { + for(short int x = 0; x < size_x; x++) { + short int j = y * MAX_SIZE + x; + short int num = board_str[j]; + if(num == 0) { cout << "--"; } + else if(num == -1) { cout << "XX"; } + else{ cout << setfill('0') << setw(2) << hex << num; } + if(x != size_x-1) { cout << " "; } + } + cout << endl; + } + cout << setfill(' '); + cout << dec; +#endif + + SET_LOOP_3: + for(int i = 0; i < line_num; i++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + short int t1 = terminals[i][0]; + short int t2 = terminals[i][1]; + short int t1_y = t1 / MAX_SIZE; + short int t1_x = t1 - MAX_SIZE * t1_y; + short int t2_y = t2 / MAX_SIZE; + short int t2_x = t2 - MAX_SIZE * t2_y; + short int dist = abs(t1_x - t2_x) + abs(t1_y - t2_y); + if(dist == 1) { + adjacents[i] = true; +#ifdef PRINT_BOARD + cout << "Line #" << i + 1 << " needs no routing" << endl; +#endif + } + } + + // Step 1 // + ROUTING_1: + for(int i = 0; i < line_num; i++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + if(adjacents[i]) continue; +#ifdef PRINT_SEARCH + cout << "Line #" << i + 1 << endl; +#endif + short int t1 = terminals[i][0]; + short int t2 = terminals[i][1]; + weights[t1] = 1; + if(search(size_x, size_y, &paths_size[i], paths[i], t1, t2, weights) < 0) { return -1; } + weights[t1] = PRIO_MAX; + } + + bool has_overlap; + short int overlap_checks[MAX_CELLS]; + short int last_target = -1; + + // Step 2 // + ROUTING_2: + for(int round = 1; round <= ROUND_LIMIT; round++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=4096 + short int target = lfsr_random() % line_num; + if(adjacents[target]) continue; + if(target == last_target) continue; + last_target = target; + unsigned short int round_weight = new_weight(round); + +#ifdef PRINT_SEARCH + cout << "Line #" << target + 1 << "(round: " << round << ", weight: " << round_weight << ")" << endl; +#endif + + short int t1 = terminals[target][0]; + short int t2 = terminals[target][1]; + + WEIGHT_UPDATE_1: + for(short int p = 0; p < paths_size[target]; p++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=128 + weights[paths[target][p]] = 1; + } + WEIGHT_UPDATE_2: + for(int i = 0; i < line_num; i++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + if(i == target) continue; + WEIGHT_UPDATE_2_1: + for(short int p = 0; p < paths_size[i]; p++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=128 + weights[paths[i][p]] = round_weight; + } + } + weights[t1] = 1; + search(size_x, size_y, &paths_size[target], paths[target], t1, t2, weights); + weights[t1] = PRIO_MAX; + + has_overlap = false; + OVERLAP_CHECK_1: + for(short int j = 0; j < MAX_CELLS; j++) { + short int y = j / MAX_SIZE; + short int x = j - MAX_SIZE * y; + if(x >= size_x || y >= size_y) continue; + short int num = board_str[j]; + if(num > 0 || num < 0) { overlap_checks[j] = 1; } + else { overlap_checks[j] = 0; } + } + OVERLAP_CHECK_2: + for(int i = 0; i < line_num; i++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + OVERLAP_CHECK_2_1: + for(short int p = 0; p < paths_size[i]; p++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=128 + short int cell_id = paths[i][p]; + if(overlap_checks[cell_id] == 1) { + has_overlap = true; + break; + } + overlap_checks[cell_id] = 1; + } + if(has_overlap) break; + } + if(!has_overlap) break; + } + + if(has_overlap) { // Cannot solve + return -1; + } + + int total_wire_length = 0; + OUTPUT_1: + for(short int i = 0; i < line_num; i++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + total_wire_length += paths_size[i]; + OUTPUT_1_1: + for(short int p = 0; p < paths_size[i]; p++) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=128 + short int cell_id = paths[i][p]; + board_str[cell_id] = i + 1; + } + } + +#ifdef PRINT_BOARD + cout << "== Print answer ==" << endl; + for(short int y = 0; y < size_y; y++) { + for(short int x = 0; x < size_x; x++) { + short int j = y * MAX_SIZE + x; + short int num = board_str[j]; + if(num == 0) { cout << "--"; } + else if(num == -1) { cout << "XX"; } + else{ cout << setfill('0') << setw(2) << hex << num; } + if(x != size_x-1) { cout << " "; } + } + cout << endl; + } + cout << setfill(' '); + cout << dec; +#endif + + return total_wire_length; +} + +int search(short int size_x, short int size_y, short int *path_size, unsigned short int path[MAX_PATH], unsigned short int start, unsigned short int goal, unsigned short int w[MAX_CELLS]) { + + unsigned short int dist[MAX_CELLS]; + unsigned short int prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for(int j = 0; j < MAX_CELLS; j++) { +//#pragma HLS UNROLL factor=2 + dist[j] = PRIO_MAX; + } + + unsigned short int pq_len = 0; + bool is_empty = true; + unsigned int pq_nodes[MAX_PQ]; + + short int goal_y = goal / MAX_SIZE; + short int goal_x = goal - MAX_SIZE * goal_y; + + dist[start] = 0; + enqueue(pq_nodes, 0, start, &pq_len, &is_empty); + + bool find_path = false; + SEARCH_BODY: + while(!is_empty) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 + + unsigned short int prev_cost; + unsigned short int s; + dequeue(pq_nodes, &prev_cost, &s, &pq_len, &is_empty); + + unsigned short int dist_s = dist[s]; + + if(s == goal) { + find_path = true; + break; + } + + unsigned short int cost = w[s]; + short int s_y = s / MAX_SIZE; + short int s_x = s - MAX_SIZE * s_y; + + SEARCH_ADJACENTS: + for(int a = 0; a < 4; a++) { + short int d_x = s_x; + short int d_y = s_y; + switch(a) { + case 0: d_x -= 1; break; + case 1: d_x += 1; break; + case 2: d_y -= 1; break; + case 3: d_y += 1; break; + } + if(d_x >= 0 && d_x < size_x && d_y >= 0 && d_y < size_y) { + unsigned short int d = d_y * MAX_SIZE + d_x; + if(w[d] == PRIO_MAX && d != goal) continue; + + unsigned short int dist_d = dist_s + cost; + if(dist_d < dist[d]) { + dist[d] = dist_d; + prev[d] = s; + dist_d += abs(d_x - goal_x) + abs(d_y - goal_y); + enqueue(pq_nodes, dist_d, d, &pq_len, &is_empty); + } + } + } + } + if(!find_path){ return -1; } + + unsigned short int t = prev[goal]; + short int p = 0; +#ifdef PRINT_SEARCH + cout << "Path: "; +#endif + SEARCH_BACKTRACK: + while(t != start) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=128 +#ifdef PRINT_SEARCH + cout << "(" << t % MAX_SIZE << ", " << t / MAX_SIZE << ")"; +#endif + path[p] = t; + p++; + t = prev[t]; + } +#ifdef PRINT_SEARCH + cout << endl; +#endif + *path_size = p; + + return 0; +} + +// Enqueue (Insert an element) +void enqueue(unsigned int pq_nodes[MAX_PQ], unsigned short int priority, unsigned short int data, unsigned short int *pq_len, bool *is_empty) { +//#pragma HLS INLINE + + (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed + // Note that last element is not always the lowest priority one. // + + unsigned short int i = (*pq_len); + unsigned short int p = (*pq_len) >> 1; // parent node + + ENQUEUE_LOOP: + while (i > 1 && (unsigned short int)(pq_nodes[p] >> DATA_BIT) >= priority) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=12 + pq_nodes[i] = pq_nodes[p]; + i = p; + p = p >> 1; // parent node + } + pq_nodes[i] = ((unsigned int)priority << DATA_BIT) | (unsigned int)data; + *is_empty = false; +} + +// Dequeue (Extract and remove the top element) +void dequeue(unsigned int pq_nodes[MAX_PQ], unsigned short int *ret_priority, unsigned short int *ret_data, unsigned short int *pq_len, bool *is_empty) { +//#pragma HLS INLINE + + *ret_priority = (unsigned short int)(pq_nodes[1] >> DATA_BIT); + *ret_data = (unsigned short int)(pq_nodes[1] & DATA_MASK); + + unsigned short int i = 1; // root node + unsigned short int last_priority = (unsigned short int)(pq_nodes[*pq_len] >> DATA_BIT); // Priority of last element + + DEQUEUE_LOOP: + while (!(i >> (PQ_BIT-1))) { +//#pragma HLS LOOP_TRIPCOUNT min=1 max=12 + unsigned short int c1 = i << 1; // child node (L) + unsigned short int c2 = c1 + 1; // child node (R) + if (c1 < *pq_len && (unsigned short int)(pq_nodes[c1] >> DATA_BIT) <= last_priority) { + if (c2 < *pq_len && (unsigned short int)(pq_nodes[c2] >> DATA_BIT) <= (unsigned short int)(pq_nodes[c1] >> DATA_BIT)) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + pq_nodes[i] = pq_nodes[c1]; + i = c1; + } + } + else { + if (c2 < *pq_len && (unsigned short int)(pq_nodes[c2] >> DATA_BIT) <= last_priority) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + break; + } + } + } + pq_nodes[i] = pq_nodes[*pq_len]; + (*pq_len)--; + if ((*pq_len) == 0) { *is_empty = true; } +} diff --git a/solver_python/solver.hpp b/solver_python/solver.hpp new file mode 100644 index 0000000000000000000000000000000000000000..692ea9ab079cbf1e93fe96f7814b609b43d5c559 --- /dev/null +++ b/solver_python/solver.hpp @@ -0,0 +1,36 @@ +#ifndef __SOLVER_HPP__ +#define __SOLVER_HPP__ + +#include "/usr/include/python3.5m/Python.h" + +#include +#include + +#include "param.hpp" +#include "tools.hpp" + +using namespace std; + +int solver(uint32_t seed[3], short int W, short int H, short int blocks, short int line_num, short int block_info[][5][3], short int line_info[][2][5], short int *pwi, short int *phi, short int opt_result[]); + +void lfsr_random_init(uint32_t seed, uint32_t seed_x, uint32_t seed_y); +uint32_t lfsr_random(); +uint32_t lfsr_x_random(); +uint32_t lfsr_y_random(); + +void global_placement(short int W, short int H, short int line_num, short int blocks, short int block_info[][5][3], short int line_info[][2][5], pair block_place_global[]); +float calcPlaceCost(short int line_num, short int line_info[][2][5], pair block_place_global[]); +bool local_placement_with_routing_1(short int line_num, short int blocks, short int *pwi, short int *phi, short int block_info[][5][3], pair block_place_global[], short int opt_result[]); +bool local_placement_with_routing_2(short int line_num, short int blocks, short int *pwi, short int *phi, short int block_info[][5][3], short int opt_result[]); +pair add_pair(pair x, pair y); +pair sub_pair(pair x, pair y); + +unsigned short int new_weight(unsigned short int x); + +int router(short int size_x, short int size_y, short int line_num, short int board_str[MAX_CELLS]); + +int search(short int size_x, short int size_y, short int *path_size, unsigned short int path[MAX_PATH], unsigned short int start, unsigned short int goal, unsigned short int w[MAX_CELLS]); +void enqueue(unsigned int pq_nodes[MAX_PQ], unsigned short int priority, unsigned short int data, unsigned short int *pq_len, bool *is_empty); +void dequeue(unsigned int pq_nodes[MAX_PQ], unsigned short int *ret_priority, unsigned short int *ret_data, unsigned short int *pq_len, bool *is_empty); + +#endif /* __SOLVER_HPP__ */ diff --git a/solver_python/tools.cpp b/solver_python/tools.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08a665e88c34f36859c958af8432e9da0a8d178a --- /dev/null +++ b/solver_python/tools.cpp @@ -0,0 +1,45 @@ +#include "tools.hpp" + +void output_to_file(char *f_name, short int line_num, short int blocks, short int wi, short int hi, short int board[], pair block_place[]) { + + ofstream outputfile(f_name); + + outputfile << "SIZE " << wi << "X" << hi << endl; + for(short int q = 0; q < hi; q++) { + for(short int p = 0; p < wi; p++) { + short int n = board[q*MAX_SIZE+p]; + if(n == 0) { outputfile << 0; } + else if(n == -1) { outputfile << 0; } + else{ outputfile << n; } + if(p != wi-1) { outputfile << ", "; } + } + outputfile << endl; + } + outputfile << setfill(' '); + outputfile << dec; + for(int i = 1; i <= blocks; i++) { + outputfile << "BLOCK#" << i << " @(" << block_place[i].first << "," << block_place[i].second << ")" << endl; + } + + outputfile.close(); +} + +void show_result(short int line_num, short int blocks, short int wi, short int hi, short int board[], pair block_place[]) { + + // This shows a number from 1 to 255 + for(short int q = 0; q < hi; q++) { + for(short int p = 0; p < wi; p++) { + short int n = board[q*MAX_SIZE+p]; + if(n == 0) { cout << "--"; } + else if(n == -1) { cout << "XX"; } + else{ cout << setfill('0') << setw(2) << hex << n; } + if(p != wi-1) { cout << " "; } + } + cout << endl; + } + cout << setfill(' '); + cout << dec; + //for(int i = 1; i <= blocks; i++) { + // cout << "BLOCK#" << i << " @(" << block_place[i].first << "," << block_place[i].second << ")" << endl; + //} +} diff --git a/solver_python/tools.hpp b/solver_python/tools.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fa794d9197c92617727084675c52d5cd21779b81 --- /dev/null +++ b/solver_python/tools.hpp @@ -0,0 +1,15 @@ +#ifndef __TOOLS_HPP__ +#define __TOOLS_HPP__ + +using namespace std; + +#include +#include // for setw +#include + +#include "param.hpp" + +void output_to_file(char *f_name, short int line_num, short int blocks, short int wi, short int hi, short int board[], pair block_place[]); +void show_result(short int line_num, short int blocks, short int wi, short int hi, short int board[], pair block_place[]); + +#endif /* __TOOLS_HPP__ */ diff --git a/solver_soft/Makefile b/solver_soft/Makefile old mode 100755 new mode 100644 index 281361b44f4c2bd57a5d1964d3b4496c6a44f471..9a19afdb532f6f6762920af887d4467450bc72bc --- a/solver_soft/Makefile +++ b/solver_soft/Makefile @@ -2,7 +2,7 @@ TARGET = sim OBJS = $(CPPS:.cpp=.o) CPPS = $(wildcard *.cpp) CXX = g++ -CXXFLAGS = -O3 +CXXFLAGS = -std=c++11 -O3 all: $(TARGET) diff --git a/solver_soft/answer/A521.txt b/solver_soft/answer/A521.txt new file mode 100644 index 0000000000000000000000000000000000000000..17d36aeff1287976241090049a940b033759a369 --- /dev/null +++ b/solver_soft/answer/A521.txt @@ -0,0 +1,32 @@ +SIZE 20X11 +0, 0, 0, 8, 8, 0, 3, 3, 3, 0, 0, 7, 0, 6, 15, 15, 15, 15, 15, 0 +0, 2, 3, 0, 8, 0, 3, 0, 3, 7, 7, 7, 6, 6, 0, 9, 9, 0, 0, 5 +0, 2, 3, 8, 8, 0, 3, 0, 0, 0, 0, 0, 0, 12, 0, 0, 9, 5, 5, 5 +0, 2, 3, 3, 0, 0, 3, 11, 0, 0, 0, 0, 12, 12, 0, 0, 0, 1, 0, 0 +2, 2, 0, 3, 3, 3, 3, 11, 0, 0, 0, 0, 12, 1, 0, 0, 1, 1, 0, 0 +2, 0, 0, 0, 0, 0, 14, 11, 11, 11, 11, 12, 12, 1, 0, 0, 1, 0, 0, 0 +0, 0, 0, 0, 4, 4, 14, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 +0, 10, 10, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 13, 13, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 13, 0, 13, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +BLOCK#1 @(7,1) +BLOCK#2 @(7,6) +BLOCK#3 @(18,0) +BLOCK#4 @(8,0) +BLOCK#5 @(10,1) +BLOCK#6 @(0,4) +BLOCK#7 @(10,3) +BLOCK#8 @(2,0) +BLOCK#9 @(13,1) +BLOCK#10 @(0,7) +BLOCK#11 @(10,3) +BLOCK#12 @(16,1) +BLOCK#13 @(3,6) +BLOCK#14 @(0,0) +BLOCK#15 @(2,6) +BLOCK#16 @(13,4) +BLOCK#17 @(5,5) +BLOCK#18 @(4,1) +BLOCK#19 @(11,0) +BLOCK#20 @(8,2) diff --git a/solver_soft/answer/A528.txt b/solver_soft/answer/A528.txt new file mode 100644 index 0000000000000000000000000000000000000000..b812a81f8df8459956e0f998635fe708d5102f07 --- /dev/null +++ b/solver_soft/answer/A528.txt @@ -0,0 +1,21 @@ +SIZE 10X10 +0, 0, 8, 8, 0, 6, 6, 6, 0, 0 +0, 0, 8, 0, 8, 4, 0, 0, 0, 0 +0, 0, 8, 8, 8, 4, 0, 0, 0, 0 +0, 0, 0, 0, 0, 4, 4, 4, 4, 4 +0, 0, 5, 5, 5, 5, 5, 5, 5, 4 +2, 0, 5, 0, 0, 0, 1, 1, 0, 1 +2, 2, 5, 5, 0, 7, 0, 1, 1, 1 +0, 2, 0, 5, 0, 7, 3, 0, 0, 0 +0, 0, 0, 5, 0, 7, 3, 0, 0, 0 +0, 0, 0, 5, 5, 5, 5, 0, 0, 0 +BLOCK#1 @(3,0) +BLOCK#2 @(0,0) +BLOCK#3 @(3,5) +BLOCK#4 @(5,0) +BLOCK#5 @(7,0) +BLOCK#6 @(8,4) +BLOCK#7 @(4,8) +BLOCK#8 @(6,5) +BLOCK#9 @(0,3) +BLOCK#10 @(0,7) diff --git a/solver_soft/answer/A556.txt b/solver_soft/answer/A556.txt new file mode 100644 index 0000000000000000000000000000000000000000..3a0ea37756d2bd04a64197fc3cfbee5093a11b76 --- /dev/null +++ b/solver_soft/answer/A556.txt @@ -0,0 +1,34 @@ +SIZE 17X13 +0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 +0, 0, 0, 3, 0, 11, 0, 0, 13, 14, 0, 0, 6, 8, 0, 0, 0 +0, 0, 0, 3, 0, 11, 0, 13, 13, 14, 14, 14, 6, 12, 12, 12, 0 +2, 2, 10, 10, 0, 11, 13, 13, 7, 7, 7, 6, 6, 0, 0, 12, 0 +0, 2, 2, 0, 11, 11, 7, 7, 7, 0, 9, 9, 4, 0, 12, 12, 0 +0, 0, 0, 0, 1, 1, 1, 0, 0, 9, 9, 0, 4, 0, 0, 0, 0 +0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 4, 0, 0, 0, 0 +0, 0, 5, 5, 15, 4, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0 +0, 0, 15, 15, 15, 4, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +BLOCK#1 @(5,7) +BLOCK#2 @(1,2) +BLOCK#3 @(4,0) +BLOCK#4 @(0,7) +BLOCK#5 @(3,3) +BLOCK#6 @(0,8) +BLOCK#7 @(2,3) +BLOCK#8 @(6,2) +BLOCK#9 @(0,11) +BLOCK#10 @(0,3) +BLOCK#11 @(10,3) +BLOCK#12 @(7,0) +BLOCK#13 @(0,9) +BLOCK#14 @(9,4) +BLOCK#15 @(12,0) +BLOCK#16 @(3,9) +BLOCK#17 @(0,0) +BLOCK#18 @(12,3) +BLOCK#19 @(10,0) +BLOCK#20 @(14,0) diff --git a/solver_soft/answer/A612.txt b/solver_soft/answer/A612.txt new file mode 100644 index 0000000000000000000000000000000000000000..6501a450a812d74f001ab021aea5792ed8017027 --- /dev/null +++ b/solver_soft/answer/A612.txt @@ -0,0 +1,19 @@ +SIZE 10X8 +0, 0, 0, 0, 4, 0, 0, 2, 2, 2 +0, 3, 0, 0, 4, 4, 4, 2, 0, 2 +0, 3, 7, 7, 0, 0, 1, 1, 0, 2 +0, 0, 5, 7, 0, 0, 0, 0, 0, 2 +0, 0, 5, 7, 8, 8, 0, 0, 0, 2 +5, 5, 5, 7, 8, 6, 6, 0, 0, 2 +0, 0, 0, 7, 8, 8, 2, 2, 2, 2 +0, 0, 7, 7, 0, 0, 0, 0, 0, 0 +BLOCK#1 @(0,1) +BLOCK#2 @(0,0) +BLOCK#3 @(0,3) +BLOCK#4 @(5,3) +BLOCK#5 @(0,6) +BLOCK#6 @(7,1) +BLOCK#7 @(5,0) +BLOCK#8 @(3,0) +BLOCK#9 @(0,2) +BLOCK#10 @(6,4) diff --git a/solver_soft/answer/A627.txt b/solver_soft/answer/A627.txt new file mode 100644 index 0000000000000000000000000000000000000000..7eaddb951e03e1c08007bf99fdb5d37350e0825c --- /dev/null +++ b/solver_soft/answer/A627.txt @@ -0,0 +1,36 @@ +SIZE 13X15 +0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0 +2, 2, 2, 0, 0, 0, 7, 0, 8, 8, 7, 7, 0 +0, 0, 2, 0, 0, 0, 7, 0, 0, 8, 0, 0, 0 +0, 3, 3, 0, 0, 0, 7, 0, 8, 8, 5, 5, 0 +3, 3, 0, 1, 1, 1, 8, 8, 8, 0, 0, 5, 0 +3, 0, 6, 4, 0, 1, 0, 0, 0, 0, 0, 5, 0 +0, 0, 6, 4, 1, 1, 10, 10, 0, 0, 0, 5, 0 +0, 0, 4, 4, 10, 10, 10, 0, 0, 0, 0, 5, 0 +0, 0, 4, 0, 10, 0, 0, 0, 0, 5, 5, 5, 0 +0, 0, 4, 0, 10, 0, 0, 0, 0, 5, 0, 0, 0 +0, 0, 0, 0, 10, 0, 0, 0, 0, 5, 0, 0, 0 +0, 0, 0, 10, 10, 5, 5, 5, 5, 5, 0, 0, 0 +0, 0, 0, 10, 0, 5, 0, 0, 0, 0, 0, 0, 0 +9, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 +9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +BLOCK#1 @(1,2) +BLOCK#2 @(9,2) +BLOCK#3 @(5,9) +BLOCK#4 @(0,0) +BLOCK#5 @(7,1) +BLOCK#6 @(7,5) +BLOCK#7 @(0,12) +BLOCK#8 @(5,2) +BLOCK#9 @(0,4) +BLOCK#10 @(0,8) +BLOCK#11 @(3,4) +BLOCK#12 @(1,10) +BLOCK#13 @(0,6) +BLOCK#14 @(1,6) +BLOCK#15 @(5,8) +BLOCK#16 @(11,0) +BLOCK#17 @(0,14) +BLOCK#18 @(2,8) +BLOCK#19 @(3,0) +BLOCK#20 @(4,12) diff --git a/solver_soft/answer/A639.txt b/solver_soft/answer/A639.txt new file mode 100644 index 0000000000000000000000000000000000000000..4145f14b2ea085a64516853fad2353f51ba426c2 --- /dev/null +++ b/solver_soft/answer/A639.txt @@ -0,0 +1,37 @@ +SIZE 13X16 +0, 3, 3, 0, 9, 0, 10, 0, 0, 0, 0, 0, 0 +0, 3, 0, 0, 9, 0, 10, 0, 0, 0, 0, 0, 0 +0, 3, 0, 0, 9, 9, 10, 0, 5, 0, 0, 0, 0 +4, 4, 4, 4, 0, 9, 10, 0, 5, 5, 0, 0, 0 +0, 0, 0, 0, 0, 9, 10, 10, 7, 5, 0, 0, 0 +0, 0, 0, 0, 9, 9, 0, 0, 7, 5, 0, 0, 0 +0, 0, 9, 9, 9, 7, 7, 7, 7, 5, 0, 0, 0 +0, 0, 0, 0, 7, 7, 5, 5, 5, 5, 0, 0, 0 +0, 0, 0, 7, 7, 6, 8, 0, 0, 0, 0, 0, 0 +0, 0, 2, 0, 0, 6, 8, 0, 0, 0, 0, 0, 0 +1, 1, 2, 0, 0, 6, 8, 0, 0, 0, 0, 0, 0 +1, 0, 0, 6, 6, 6, 8, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0 +8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +BLOCK#1 @(2,11) +BLOCK#2 @(2,0) +BLOCK#3 @(10,3) +BLOCK#4 @(0,0) +BLOCK#5 @(0,11) +BLOCK#6 @(2,7) +BLOCK#7 @(11,0) +BLOCK#8 @(0,9) +BLOCK#9 @(0,6) +BLOCK#10 @(5,7) +BLOCK#11 @(2,3) +BLOCK#12 @(0,3) +BLOCK#13 @(3,8) +BLOCK#14 @(4,0) +BLOCK#15 @(10,1) +BLOCK#16 @(7,3) +BLOCK#17 @(8,0) +BLOCK#18 @(7,0) +BLOCK#19 @(0,13) +BLOCK#20 @(8,0) diff --git a/solver_soft/answer/A731.txt b/solver_soft/answer/A731.txt new file mode 100644 index 0000000000000000000000000000000000000000..f7e2825539c4cf229a0ad3e311a627a40f6522ea --- /dev/null +++ b/solver_soft/answer/A731.txt @@ -0,0 +1,33 @@ +SIZE 14X12 +7, 5, 5, 5, 0, 0, 0, 0, 0, 10, 10, 0, 0, 0 +7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0 +7, 0, 0, 0, 0, 0, 0, 9, 1, 0, 0, 6, 0, 0 +4, 0, 0, 0, 0, 0, 9, 9, 1, 1, 0, 6, 0, 0 +4, 0, 0, 0, 0, 0, 9, 0, 0, 1, 0, 6, 0, 0 +0, 2, 0, 0, 0, 6, 6, 6, 0, 1, 6, 6, 0, 0 +0, 2, 0, 0, 0, 6, 8, 0, 0, 1, 6, 0, 0, 0 +0, 2, 2, 0, 6, 6, 8, 8, 0, 1, 6, 0, 0, 0 +0, 0, 0, 0, 6, 0, 0, 0, 0, 1, 6, 0, 0, 0 +0, 0, 0, 3, 6, 1, 1, 1, 1, 1, 6, 0, 0, 0 +3, 3, 3, 3, 6, 0, 0, 6, 6, 6, 6, 0, 0, 0 +0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0 +BLOCK#1 @(10,0) +BLOCK#2 @(12,0) +BLOCK#3 @(1,0) +BLOCK#4 @(0,4) +BLOCK#5 @(6,0) +BLOCK#6 @(4,3) +BLOCK#7 @(4,0) +BLOCK#8 @(0,9) +BLOCK#9 @(6,6) +BLOCK#10 @(1,4) +BLOCK#11 @(1,0) +BLOCK#12 @(8,0) +BLOCK#13 @(6,4) +BLOCK#14 @(2,6) +BLOCK#15 @(0,0) +BLOCK#16 @(1,8) +BLOCK#17 @(3,2) +BLOCK#18 @(5,8) +BLOCK#19 @(11,0) +BLOCK#20 @(0,2) diff --git a/solver_soft/answer/A732.txt b/solver_soft/answer/A732.txt new file mode 100644 index 0000000000000000000000000000000000000000..68c103e746b7e270cc4951479047d8f3293ebc0c --- /dev/null +++ b/solver_soft/answer/A732.txt @@ -0,0 +1,35 @@ +SIZE 19X14 +0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 5, 0, 0, 0, 3, 0, 4 +0, 0, 0, 2, 2, 8, 8, 7, 0, 0, 0, 0, 5, 0, 0, 0, 3, 0, 4 +0, 0, 0, 0, 0, 8, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 3, 0, 4 +0, 15, 15, 0, 0, 8, 0, 7, 7, 7, 0, 0, 0, 0, 3, 3, 3, 0, 4 +0, 0, 15, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 4 +0, 0, 10, 10, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 4 +10, 10, 10, 13, 8, 0, 0, 3, 0, 3, 3, 0, 4, 0, 0, 4, 4, 4, 4 +12, 12, 12, 13, 13, 13, 0, 3, 3, 3, 9, 9, 4, 4, 4, 4, 14, 14, 0 +1, 1, 12, 12, 0, 13, 13, 0, 0, 0, 9, 11, 11, 0, 0, 0, 0, 14, 0 +0, 1, 0, 12, 6, 0, 0, 0, 0, 0, 9, 0, 11, 0, 0, 0, 0, 14, 0 +0, 1, 9, 9, 6, 6, 6, 9, 9, 9, 9, 0, 11, 0, 0, 0, 0, 14, 0 +0, 0, 11, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 0, 0, 0, 0, 14, 0 +0, 0, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0 +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0 +BLOCK#1 @(12,2) +BLOCK#2 @(3,6) +BLOCK#3 @(12,0) +BLOCK#4 @(7,4) +BLOCK#5 @(6,8) +BLOCK#6 @(11,6) +BLOCK#7 @(0,6) +BLOCK#8 @(15,7) +BLOCK#9 @(3,8) +BLOCK#10 @(15,0) +BLOCK#11 @(0,1) +BLOCK#12 @(0,3) +BLOCK#13 @(2,0) +BLOCK#14 @(12,5) +BLOCK#15 @(9,0) +BLOCK#16 @(1,9) +BLOCK#17 @(0,11) +BLOCK#18 @(6,1) +BLOCK#19 @(2,3) +BLOCK#20 @(9,1) diff --git a/solver_soft/sample_A.txt b/solver_soft/sample_A.txt new file mode 100644 index 0000000000000000000000000000000000000000..16f54de4cebe6451f4e74159a1b31cbec0b2e7c4 --- /dev/null +++ b/solver_soft/sample_A.txt @@ -0,0 +1,19 @@ +SIZE 8X10 +1, 1, 1, 2, 2, 2, 2, 0 +0, 0, 4, 0, 0, 0, 2, 2 +8, 8, 4, 4, 4, 0, 4, 2 +7, 8, 0, 0, 4, 4, 4, 2 +7, 6, 0, 0, 0, 0, 2, 2 +0, 6, 6, 6, 5, 11, 0, 0 +10, 10, 10, 6, 5, 11, 0, 0 +0, 9, 5, 5, 5, 0, 0, 3 +3, 9, 3, 3, 3, 3, 3, 3 +3, 3, 3, 0, 0, 0, 0, 0 +BLOCK#1 @(0,0) +BLOCK#2 @(0,3) +BLOCK#3 @(0,6) +BLOCK#4 @(2,0) +BLOCK#5 @(5,6) +BLOCK#6 @(4,4) +BLOCK#7 @(1,6) +BLOCK#8 @(4,1) diff --git a/solver_soft/sample_Q.txt b/solver_soft/sample_Q.txt new file mode 100644 index 0000000000000000000000000000000000000000..f99ce862c4eaf2a200d2365582736cf36ccc661a --- /dev/null +++ b/solver_soft/sample_Q.txt @@ -0,0 +1,37 @@ +SIZE 10X10 +BLOCK_NUM 8 + +BLOCK#1 1X4 +1 ++ +8 +7 + +BLOCK#2 3X2 +0,8,0 +7,6,+ + +BLOCK#3 2X3 +10,0 + +,0 + 3,9 + +BLOCK#4 2X2 +1,2 +4,+ + +BLOCK#5 3X2 +11,+,+ + 0,0,3 + +BLOCK#6 3X2 +0, +,2 +5,11,0 + +BLOCK#7 3X2 +0,10,6 +9, 5,0 + +BLOCK#8 3X2 ++,+,0 +0,+,4 \ No newline at end of file diff --git a/solver_soft/solver.cpp b/solver_soft/solver.cpp old mode 100755 new mode 100644 diff --git a/solver_soft/solver.hpp b/solver_soft/solver.hpp old mode 100755 new mode 100644 diff --git a/solver_soft/tools.hpp b/solver_soft/tools.hpp index 4ffdb2ab609296cc32eb892f2eef545ac9c64b4f..947061997e28d1c3e3b610713d593b37bf255ca9 100644 --- a/solver_soft/tools.hpp +++ b/solver_soft/tools.hpp @@ -13,4 +13,4 @@ void usage(); void output_to_file(char *f_name, short int line_num, short int blocks, short int wi, short int hi, short int board[], pair block_place[]); void show_result(short int line_num, short int blocks, short int wi, short int hi, short int board[], pair block_place[]); -#endif /* __TOOLS_HPP__ */ \ No newline at end of file +#endif /* __TOOLS_HPP__ */