├── docs ├── GA.png ├── 模拟退火算法流程.jpeg └── Metropolis.png ├── .gitignore ├── cdn ├── global.cpp ├── lib │ ├── lib_time.h │ └── lib_io.h ├── global.h ├── deploy.h ├── cdn.cpp ├── CMakeLists.txt ├── io.cpp ├── MCMF.h └── deploy.cpp ├── case_example ├── 0 │ ├── 111.txt │ ├── 123 .txt │ ├── 321.txt │ ├── case0.txt │ ├── case1.txt │ ├── case3.txt │ ├── case4.txt │ └── case2.txt └── 1 │ └── 0 │ ├── case1.txt │ ├── case3 2.txt │ ├── case3.txt │ ├── case8.txt │ ├── case6 2.txt │ ├── case6.txt │ ├── case7 2.txt │ ├── case7.txt │ ├── case2 2.txt │ ├── case2.txt │ ├── case5.txt │ ├── case0 2.txt │ ├── case0.txt │ ├── case4 2.txt │ └── case4.txt ├── README.md └── LICENSE /docs/GA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXIOMZK/cdn/HEAD/docs/GA.png -------------------------------------------------------------------------------- /docs/模拟退火算法流程.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXIOMZK/cdn/HEAD/docs/模拟退火算法流程.jpeg -------------------------------------------------------------------------------- /docs/Metropolis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AXIOMZK/cdn/HEAD/docs/Metropolis.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | cmake-build-debug/ 3 | .idea/ -------------------------------------------------------------------------------- /cdn/global.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 张琨 on 2017/4/2. 3 | // 4 | 5 | 6 | #include "global.h" 7 | int isExit=1; -------------------------------------------------------------------------------- /case_example/0/111.txt: -------------------------------------------------------------------------------- 1 | 4 5 1 2 | 3 | 100 4 | 5 | 0 1 4 5 6 | 0 2 5 4 7 | 0 3 1 3 8 | 1 3 2 1 9 | 2 3 3 2 10 | 11 | 0 1 5 -------------------------------------------------------------------------------- /case_example/0/123 .txt: -------------------------------------------------------------------------------- 1 | 4 5 1 2 | 3 | 100 4 | 5 | 0 1 4 5 6 | 0 2 5 4 7 | 0 3 1 3 8 | 1 3 2 1 9 | 2 3 3 2 10 | 11 | 0 1 5 -------------------------------------------------------------------------------- /case_example/0/321.txt: -------------------------------------------------------------------------------- 1 | 4 5 1 2 | 3 | 100 4 | 5 | 0 1 4 5 6 | 0 2 4 5 7 | 0 3 1 3 8 | 1 3 2 1 9 | 2 3 3 2 10 | 11 | 0 1 5 12 | -------------------------------------------------------------------------------- /cdn/lib/lib_time.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_TIME_H__ 2 | #define __LIB_TIME_H__ 3 | 4 | //打印时间。入参为打印信息头 5 | void print_time(const char * const head); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /cdn/global.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 张琨 on 2017/4/2. 3 | // 4 | 5 | 6 | #ifndef CDN_GLOBAL_H 7 | #define CDN_GLOBAL_H 8 | extern int isExit ;//定时器标志 9 | #endif //CDN_GLOBAL_H 10 | -------------------------------------------------------------------------------- /cdn/lib/lib_io.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_IO_H__ 2 | #define __LIB_IO_H__ 3 | 4 | #define MAX_EDGE_NUM (2000 * 20) 5 | 6 | //读取文件并按行输出到buff。 7 | //buff为一个指针数组,每一个元素是一个字符指针,对应文件中一行的内容。 8 | //spec为允许解析的最大行数。 9 | extern int read_file(char ** const buff, const unsigned int spec, const char * const filename); 10 | 11 | //将result缓冲区中的内容写入文件,写入方式为覆盖写入 12 | extern void write_result(const char * const buff,const char * const filename); 13 | 14 | //释放读文件的缓冲区 15 | extern void release_buff(char ** const buff, const int valid_item_num); 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /cdn/deploy.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROUTE_H__ 2 | #define __ROUTE_H__ 3 | 4 | #include "global.h" 5 | #include 6 | #include "lib_io.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | //服务器部署编号(连接的节点号),评估带宽结构体 17 | struct SeverNoAndAroundBandwidth; 18 | //链路信息(双向) 19 | struct LinkInfo; 20 | //消费节点信息结构体 21 | struct ResumeInfo; 22 | struct Bandwidth_From_Small_To_Big; 23 | 24 | void deploy_server(char *graph[MAX_EDGE_NUM], int edge_num, char *filename); 25 | void timer(int sig); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /cdn/cdn.cpp: -------------------------------------------------------------------------------- 1 | #include "deploy.h" 2 | #include "lib_time.h" 3 | 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | print_time("Begin"); 8 | char *topo[MAX_EDGE_NUM]; 9 | int line_num; 10 | 11 | char *topo_file = argv[1]; 12 | // char *topo_file = (char *) "/Users/kingzhang.cn/Desktop/case_example/1/0/case8.txt"; 13 | 14 | line_num = read_file(topo, MAX_EDGE_NUM, topo_file); 15 | 16 | printf("line num is :%d \n", line_num); 17 | if (line_num == 0) 18 | { 19 | printf("Please input valid topo file.\n"); 20 | return -1; 21 | } 22 | 23 | char *result_file = argv[2]; 24 | // char *result_file = (char *) "/Users/kingzhang.cn/Desktop/Mac_Result.txt"; 25 | 26 | deploy_server(topo, line_num, result_file); 27 | 28 | release_buff(topo, line_num); 29 | 30 | print_time("End"); 31 | 32 | return 0; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /cdn/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | #编译目标环境、编译器及其路径设置 5 | #SET(CMAKE_SYSTEM_NAME Linux) 6 | SET(CMAKE_C_COMPILER /usr/local/Cellar/gcc@4.8/4.8.5/bin/gcc-4.8) 7 | SET(CMAKE_CXX_COMPILER /usr/local/Cellar/gcc@4.8/4.8.5/bin/g++-4.8) 8 | set(CMAKE_FIND_ROOT_PATH /usr/local/Cellar/gcc@4.8/4.8.5) 9 | # 项目信息 10 | project(cdn) 11 | 12 | # include路径 13 | include_directories(${PROJECT_SOURCE_DIR}/lib) 14 | 15 | # 设置可执行文件生成路径 16 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) 17 | 18 | # 生成debug版本 19 | SET(CMAKE_BUILD_TYPE "release") 20 | if (CMAKE_BUILD_TYPE STREQUAL debug) 21 | add_definitions(-D_DEBUG) 22 | endif () 23 | SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb -std=c++11") 24 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -std=c++11") 25 | 26 | # 查找当前目录下的所有源文件 27 | # 并将名称保存到 DIR_LIB_SRCS 变量 28 | aux_source_directory(. DIR_SRCS) 29 | 30 | # 指定生成目标 31 | add_executable(cdn ${DIR_SRCS} MCMF.cpp MCMF.h global.h global.cpp io.cpp cdn.cpp deploy.cpp deploy.h ) 32 | -------------------------------------------------------------------------------- /case_example/0/case0.txt: -------------------------------------------------------------------------------- 1 | 50 96 9 2 | 3 | 260 4 | 5 | 0 26 15 7 6 | 0 14 20 3 7 | 0 12 27 1 8 | 0 9 1 5 9 | 0 7 26 10 10 | 0 1 5 5 11 | 0 2 40 10 12 | 0 3 31 3 13 | 0 4 27 9 14 | 1 43 19 2 15 | 1 9 33 2 16 | 1 35 48 1 17 | 1 47 25 5 18 | 1 23 28 4 19 | 1 18 22 4 20 | 1 17 5 5 21 | 1 2 25 6 22 | 1 3 1 6 23 | 1 4 26 9 24 | 2 19 19 3 25 | 2 28 19 2 26 | 2 27 41 9 27 | 2 3 25 3 28 | 2 4 50 5 29 | 3 47 17 8 30 | 3 13 43 5 31 | 3 37 49 6 32 | 3 32 36 1 33 | 3 4 22 7 34 | 4 23 46 6 35 | 4 11 27 1 36 | 4 49 7 5 37 | 4 47 40 9 38 | 4 44 26 1 39 | 4 40 8 5 40 | 5 6 7 6 41 | 5 7 5 1 42 | 6 7 44 2 43 | 8 9 3 8 44 | 8 10 50 9 45 | 9 10 17 9 46 | 11 19 38 3 47 | 11 12 36 6 48 | 13 14 42 10 49 | 13 15 50 10 50 | 13 16 32 9 51 | 14 15 30 7 52 | 14 16 1 9 53 | 15 16 4 9 54 | 18 19 10 2 55 | 18 20 36 6 56 | 18 21 44 6 57 | 19 45 34 9 58 | 19 20 6 1 59 | 19 21 48 10 60 | 20 21 39 1 61 | 21 29 14 4 62 | 22 23 39 4 63 | 22 24 21 8 64 | 22 25 5 7 65 | 23 24 24 8 66 | 23 25 9 7 67 | 24 25 1 9 68 | 26 46 21 8 69 | 26 27 5 1 70 | 28 29 34 2 71 | 28 30 42 1 72 | 28 31 27 10 73 | 29 30 47 3 74 | 29 31 18 6 75 | 30 31 8 4 76 | 31 39 30 8 77 | 32 33 38 3 78 | 32 34 9 3 79 | 32 35 36 6 80 | 33 34 8 7 81 | 33 35 16 7 82 | 34 35 4 6 83 | 36 37 21 4 84 | 38 39 46 1 85 | 38 40 29 9 86 | 38 41 31 6 87 | 38 42 39 4 88 | 39 40 15 8 89 | 39 41 32 8 90 | 39 42 7 9 91 | 40 41 49 6 92 | 40 42 49 7 93 | 41 42 38 1 94 | 43 44 46 10 95 | 45 46 44 3 96 | 45 47 14 1 97 | 45 48 30 10 98 | 46 47 31 3 99 | 46 48 41 7 100 | 47 48 35 5 101 | 102 | 0 43 24 103 | 1 44 15 104 | 2 22 36 105 | 3 7 22 106 | 4 37 46 107 | 5 13 40 108 | 6 15 49 109 | 7 38 63 110 | 8 34 8 111 | -------------------------------------------------------------------------------- /case_example/0/case1.txt: -------------------------------------------------------------------------------- 1 | 50 97 9 2 | 3 | 280 4 | 5 | 0 25 21 9 6 | 0 22 27 1 7 | 0 18 33 10 8 | 0 14 15 1 9 | 0 13 45 8 10 | 0 9 29 1 11 | 0 6 13 10 12 | 0 1 6 3 13 | 0 2 21 1 14 | 0 3 46 10 15 | 0 4 14 8 16 | 1 35 40 5 17 | 1 26 36 7 18 | 1 2 28 2 19 | 1 3 29 1 20 | 1 4 32 7 21 | 2 25 40 8 22 | 2 24 35 3 23 | 2 14 19 10 24 | 2 39 33 1 25 | 2 36 17 3 26 | 2 33 2 7 27 | 2 29 7 2 28 | 2 3 17 5 29 | 2 4 2 2 30 | 3 13 38 7 31 | 3 15 4 7 32 | 3 41 15 10 33 | 3 4 35 2 34 | 4 22 6 8 35 | 4 24 42 7 36 | 4 6 22 10 37 | 4 39 33 2 38 | 4 49 2 1 39 | 4 46 5 4 40 | 5 6 39 5 41 | 7 8 46 1 42 | 7 9 23 3 43 | 7 10 7 4 44 | 8 9 4 2 45 | 8 10 22 10 46 | 9 45 17 5 47 | 9 10 33 2 48 | 11 12 37 10 49 | 11 13 29 4 50 | 12 13 33 3 51 | 14 15 25 3 52 | 16 30 46 6 53 | 16 17 37 1 54 | 16 18 48 9 55 | 16 19 2 10 56 | 16 20 4 2 57 | 17 18 25 7 58 | 17 19 21 8 59 | 17 20 16 7 60 | 18 19 29 8 61 | 18 20 1 6 62 | 19 24 13 4 63 | 19 20 32 8 64 | 20 33 5 1 65 | 21 22 9 8 66 | 21 23 35 6 67 | 22 23 32 1 68 | 24 36 21 9 69 | 24 25 19 3 70 | 26 27 25 2 71 | 26 28 14 8 72 | 27 28 48 1 73 | 28 36 25 4 74 | 29 30 18 2 75 | 30 44 17 6 76 | 31 32 38 2 77 | 31 33 20 10 78 | 32 33 19 1 79 | 34 35 2 6 80 | 34 36 38 6 81 | 34 37 49 2 82 | 35 36 6 9 83 | 35 37 40 3 84 | 36 37 32 10 85 | 38 39 44 4 86 | 38 40 23 6 87 | 39 40 37 10 88 | 40 44 21 2 89 | 41 42 23 1 90 | 41 43 25 1 91 | 42 43 48 1 92 | 44 45 19 3 93 | 44 46 4 1 94 | 44 47 35 9 95 | 44 48 46 10 96 | 45 46 49 5 97 | 45 47 38 1 98 | 45 48 29 5 99 | 46 47 22 8 100 | 46 48 16 7 101 | 47 48 50 7 102 | 103 | 0 35 57 104 | 1 5 10 105 | 2 6 32 106 | 3 7 28 107 | 4 41 25 108 | 5 13 99 109 | 6 48 82 110 | 7 17 27 111 | 8 23 21 112 | -------------------------------------------------------------------------------- /case_example/0/case3.txt: -------------------------------------------------------------------------------- 1 | 50 97 9 2 | 3 | 300 4 | 5 | 0 10 6 1 6 | 0 26 24 10 7 | 0 6 19 3 8 | 0 1 16 2 9 | 0 2 17 2 10 | 0 3 31 10 11 | 0 4 5 1 12 | 1 6 46 5 13 | 1 16 42 9 14 | 1 9 38 1 15 | 1 2 2 2 16 | 1 3 12 5 17 | 1 4 17 3 18 | 2 35 47 4 19 | 2 11 12 7 20 | 2 3 36 2 21 | 2 4 24 7 22 | 3 41 22 3 23 | 3 48 22 8 24 | 3 40 34 8 25 | 3 37 39 3 26 | 3 31 19 1 27 | 3 27 18 3 28 | 3 25 35 4 29 | 3 20 11 1 30 | 3 17 11 5 31 | 3 14 8 8 32 | 3 4 13 2 33 | 4 16 17 5 34 | 4 47 31 2 35 | 4 45 20 2 36 | 4 39 15 4 37 | 4 38 17 4 38 | 4 36 16 9 39 | 4 32 47 3 40 | 5 6 9 7 41 | 5 7 9 7 42 | 6 7 17 10 43 | 7 19 47 4 44 | 8 12 22 3 45 | 8 9 46 10 46 | 8 10 33 4 47 | 9 10 49 10 48 | 11 12 12 8 49 | 11 13 9 6 50 | 12 13 29 7 51 | 14 15 45 3 52 | 14 16 49 7 53 | 15 16 44 2 54 | 17 18 16 6 55 | 17 19 47 10 56 | 18 30 34 4 57 | 18 19 15 5 58 | 20 21 46 1 59 | 20 22 7 4 60 | 20 23 46 4 61 | 20 24 1 6 62 | 21 22 22 1 63 | 21 23 19 7 64 | 21 24 44 4 65 | 22 23 48 6 66 | 22 24 48 1 67 | 23 24 22 9 68 | 25 26 40 3 69 | 26 39 40 8 70 | 27 28 37 5 71 | 27 29 37 2 72 | 27 30 31 1 73 | 28 29 17 4 74 | 28 30 31 8 75 | 29 30 1 3 76 | 32 33 40 8 77 | 32 34 39 4 78 | 32 35 33 1 79 | 33 34 41 9 80 | 33 35 6 2 81 | 34 35 39 1 82 | 36 37 19 9 83 | 39 40 7 3 84 | 39 41 4 10 85 | 39 42 21 8 86 | 39 43 35 7 87 | 39 44 40 5 88 | 40 41 44 8 89 | 40 42 28 5 90 | 40 43 49 2 91 | 40 44 50 9 92 | 41 42 16 7 93 | 41 43 11 6 94 | 41 44 38 4 95 | 42 43 26 5 96 | 42 44 24 5 97 | 43 44 22 10 98 | 45 46 25 1 99 | 47 48 36 3 100 | 47 49 10 9 101 | 48 49 36 5 102 | 103 | 0 47 28 104 | 1 31 14 105 | 2 22 64 106 | 3 21 47 107 | 4 29 22 108 | 5 26 55 109 | 6 33 28 110 | 7 10 32 111 | 8 35 50 112 | -------------------------------------------------------------------------------- /case_example/0/case4.txt: -------------------------------------------------------------------------------- 1 | 50 99 9 2 | 3 | 400 4 | 5 | 0 47 7 7 6 | 0 14 14 3 7 | 0 8 37 10 8 | 0 6 1 10 9 | 0 5 14 4 10 | 0 1 20 7 11 | 0 2 6 7 12 | 0 3 30 3 13 | 0 4 50 9 14 | 1 10 28 8 15 | 1 8 22 6 16 | 1 28 44 5 17 | 1 25 40 9 18 | 1 21 10 9 19 | 1 20 4 6 20 | 1 2 29 7 21 | 1 3 1 9 22 | 1 4 17 10 23 | 2 12 8 4 24 | 2 44 5 8 25 | 2 45 4 10 26 | 2 41 15 3 27 | 2 30 15 6 28 | 2 3 33 5 29 | 2 4 3 1 30 | 3 28 39 1 31 | 3 45 29 4 32 | 3 43 42 5 33 | 3 37 17 6 34 | 3 34 2 1 35 | 3 32 15 7 36 | 3 4 40 2 37 | 4 5 16 9 38 | 4 39 4 4 39 | 4 49 48 7 40 | 6 7 16 1 41 | 8 9 49 2 42 | 8 10 20 10 43 | 8 11 37 1 44 | 9 10 16 2 45 | 9 11 47 9 46 | 10 11 23 7 47 | 12 13 6 9 48 | 12 14 7 2 49 | 12 15 41 10 50 | 12 16 16 2 51 | 13 14 10 5 52 | 13 15 36 1 53 | 13 16 16 6 54 | 14 20 39 9 55 | 14 34 25 10 56 | 14 15 18 7 57 | 14 16 33 7 58 | 15 16 40 2 59 | 16 41 46 3 60 | 17 18 1 2 61 | 17 19 17 8 62 | 17 20 20 8 63 | 18 19 45 9 64 | 18 20 25 2 65 | 19 20 1 1 66 | 21 34 6 9 67 | 21 22 48 7 68 | 21 23 2 2 69 | 21 24 1 3 70 | 22 23 23 9 71 | 22 24 11 3 72 | 23 24 7 6 73 | 25 26 8 2 74 | 25 27 2 2 75 | 26 27 16 6 76 | 29 30 6 5 77 | 29 31 24 4 78 | 30 31 10 10 79 | 33 34 20 9 80 | 33 35 22 6 81 | 34 35 25 1 82 | 36 37 1 6 83 | 36 38 20 4 84 | 36 39 8 3 85 | 36 40 31 7 86 | 36 41 43 10 87 | 37 38 13 3 88 | 37 39 29 10 89 | 37 40 7 5 90 | 37 41 10 7 91 | 38 39 4 9 92 | 38 40 5 5 93 | 38 41 26 10 94 | 39 40 12 10 95 | 39 41 45 4 96 | 40 41 2 5 97 | 42 43 19 8 98 | 44 45 48 5 99 | 44 46 14 9 100 | 45 46 7 1 101 | 47 48 34 8 102 | 47 49 3 3 103 | 48 49 27 10 104 | 105 | 0 20 22 106 | 1 26 16 107 | 2 38 22 108 | 3 22 31 109 | 4 48 20 110 | 5 15 70 111 | 6 12 52 112 | 7 28 20 113 | 8 37 31 114 | -------------------------------------------------------------------------------- /case_example/0/case2.txt: -------------------------------------------------------------------------------- 1 | 50 113 9 2 | 3 | 210 4 | 5 | 0 41 42 6 6 | 0 13 8 1 7 | 0 7 6 10 8 | 0 6 40 5 9 | 0 1 43 1 10 | 0 2 12 7 11 | 0 3 27 7 12 | 0 4 22 9 13 | 1 46 5 5 14 | 1 40 23 10 15 | 1 39 2 8 16 | 1 13 22 5 17 | 1 41 46 9 18 | 1 25 48 8 19 | 1 24 9 3 20 | 1 22 3 2 21 | 1 14 36 2 22 | 1 2 5 3 23 | 1 3 36 8 24 | 1 4 38 1 25 | 2 14 32 9 26 | 2 33 13 4 27 | 2 35 32 5 28 | 2 28 32 5 29 | 2 26 29 6 30 | 2 3 40 7 31 | 2 4 17 4 32 | 3 42 12 6 33 | 3 40 33 6 34 | 3 35 46 8 35 | 3 33 14 3 36 | 3 4 9 3 37 | 4 41 16 4 38 | 4 47 7 1 39 | 4 44 21 8 40 | 5 6 6 1 41 | 7 8 21 2 42 | 7 9 2 8 43 | 8 9 1 7 44 | 9 37 2 2 45 | 10 11 31 9 46 | 10 12 41 1 47 | 10 13 28 4 48 | 11 12 14 10 49 | 11 13 31 8 50 | 12 13 9 8 51 | 14 39 28 6 52 | 14 15 38 6 53 | 16 17 13 8 54 | 16 18 40 9 55 | 16 19 33 3 56 | 16 20 14 6 57 | 16 21 7 3 58 | 16 22 8 3 59 | 16 23 12 6 60 | 17 18 18 4 61 | 17 19 47 1 62 | 17 20 34 5 63 | 17 21 18 9 64 | 17 22 25 6 65 | 17 23 8 4 66 | 18 19 40 9 67 | 18 20 1 5 68 | 18 21 21 5 69 | 18 22 44 3 70 | 18 23 7 1 71 | 19 20 17 9 72 | 19 21 41 6 73 | 19 22 22 8 74 | 19 23 27 2 75 | 20 21 27 4 76 | 20 22 15 5 77 | 20 23 23 10 78 | 21 22 46 1 79 | 21 23 13 2 80 | 22 23 45 9 81 | 27 28 17 1 82 | 27 29 47 4 83 | 27 30 38 8 84 | 27 31 1 9 85 | 28 29 46 9 86 | 28 30 5 7 87 | 28 31 2 1 88 | 29 30 11 8 89 | 29 31 39 9 90 | 30 31 21 1 91 | 32 33 49 6 92 | 34 35 12 3 93 | 34 36 48 8 94 | 34 37 5 9 95 | 34 38 23 10 96 | 35 36 17 6 97 | 35 37 49 9 98 | 35 38 33 3 99 | 36 37 11 2 100 | 36 38 6 2 101 | 37 38 43 8 102 | 39 40 29 2 103 | 40 48 44 4 104 | 41 42 10 3 105 | 41 43 31 4 106 | 42 43 20 8 107 | 43 47 14 8 108 | 45 46 9 5 109 | 45 47 10 10 110 | 45 48 10 4 111 | 45 49 50 5 112 | 46 47 26 5 113 | 46 48 41 9 114 | 46 49 27 3 115 | 47 48 22 4 116 | 47 49 50 8 117 | 48 49 8 5 118 | 119 | 0 38 58 120 | 1 5 4 121 | 2 23 47 122 | 3 18 80 123 | 4 29 70 124 | 5 21 50 125 | 6 12 41 126 | 7 31 34 127 | 8 48 47 128 | -------------------------------------------------------------------------------- /cdn/io.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_LINE_LEN 55000 12 | 13 | #define INLINE static __inline 14 | #ifdef _DEBUG 15 | #define PRINT printf 16 | #else 17 | #define PRINT(...) 18 | #endif 19 | 20 | 21 | INLINE void write_file(const bool cover, const char * const buff, const char * const filename); 22 | 23 | 24 | void print_time(const char *head) 25 | { 26 | #ifdef _DEBUG 27 | struct timeb rawtime; 28 | struct tm * timeinfo; 29 | ftime(&rawtime); 30 | timeinfo = localtime(&rawtime.time); 31 | 32 | static int ms = rawtime.millitm; 33 | static unsigned long s = rawtime.time; 34 | int out_ms = rawtime.millitm - ms; 35 | unsigned long out_s = rawtime.time - s; 36 | ms = rawtime.millitm; 37 | s = rawtime.time; 38 | 39 | if (out_ms < 0) 40 | { 41 | out_ms += 1000; 42 | out_s -= 1; 43 | } 44 | printf("%s date/time is: %s \tused time is %lu s %d ms.\n", head, asctime(timeinfo), out_s, out_ms); 45 | #endif 46 | } 47 | 48 | int read_file(char ** const buff, const unsigned int spec, const char * const filename) 49 | { 50 | FILE *fp = fopen(filename, "r"); 51 | if (fp == NULL) 52 | { 53 | PRINT("Fail to open file %s, %s.\n", filename, strerror(errno)); 54 | return 0; 55 | } 56 | PRINT("Open file %s OK.\n", filename); 57 | 58 | char line[MAX_LINE_LEN + 2]; 59 | unsigned int cnt = 0; 60 | while ((cnt < spec) && !feof(fp)) 61 | { 62 | line[0] = 0; 63 | if (fgets(line, MAX_LINE_LEN + 2, fp) == NULL) continue; 64 | if (line[0] == 0) continue; 65 | buff[cnt] = (char *)malloc(MAX_LINE_LEN + 2); 66 | strncpy(buff[cnt], line, MAX_LINE_LEN + 2 - 1); 67 | buff[cnt][MAX_LINE_LEN + 1] = 0; 68 | cnt++; 69 | } 70 | fclose(fp); 71 | PRINT("There are %d lines in file %s.\n", cnt, filename); 72 | 73 | return cnt; 74 | } 75 | 76 | void write_result(const char * const buff,const char * const filename) 77 | { 78 | // 以覆盖的方式写入 79 | write_file(1, buff, filename); 80 | 81 | } 82 | 83 | void release_buff(char ** const buff, const int valid_item_num) 84 | { 85 | for (int i = 0; i < valid_item_num; i++) 86 | free(buff[i]); 87 | } 88 | 89 | INLINE void write_file(const bool cover, const char * const buff, const char * const filename) 90 | { 91 | if (buff == NULL) 92 | return; 93 | 94 | const char *write_type = cover ? "w" : "a";//1:覆盖写文件,0:追加写文件 95 | FILE *fp = fopen(filename, write_type); 96 | if (fp == NULL) 97 | { 98 | PRINT("Fail to open file %s, %s.\n", filename, strerror(errno)); 99 | return; 100 | } 101 | PRINT("Open file %s OK.\n", filename); 102 | fputs(buff, fp); 103 | fputs("\n", fp); 104 | fclose(fp); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /cdn/MCMF.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 张琨 on 2017/3/29. 3 | // 4 | 5 | #ifndef CDN_MCMF_H 6 | #define CDN_MCMF_H 7 | 8 | #include "global.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #ifdef _DEBUG 19 | #define PRINT printf 20 | #else 21 | #define PRINT(...) 22 | #endif 23 | 24 | using namespace std; 25 | 26 | 27 | struct SeverNoAndAroundBandwidth 28 | { 29 | int ServerNo; 30 | int ServeAroundBandwidth; 31 | }; 32 | //链路信息(双向) 33 | struct LinkInfo 34 | { 35 | int total_bandwidth = 0; 36 | int network_hire = INT_MAX; 37 | }; 38 | //消费节点信息结构体 39 | struct ResumeInfo 40 | { 41 | int node_NO;//消费节点连接的网络节点编号 42 | int need_bandwidth;//需求带宽 43 | }; 44 | 45 | struct Bandwidth_From_Small_To_Big 46 | { 47 | bool operator()(const SeverNoAndAroundBandwidth &left, const SeverNoAndAroundBandwidth &right) const 48 | { 49 | return (left.ServeAroundBandwidth < right.ServeAroundBandwidth); 50 | } 51 | }; 52 | 53 | struct SeverSetAndCost 54 | { 55 | set SetSeverNO;//服务器编号集合 56 | int cost;//对应的成本 57 | }; 58 | 59 | //struct pro_serverFromSmallToBig 60 | //{ 61 | // bool operator()(const SeverSetAndCost &left, const SeverSetAndCost &right) const 62 | // { 63 | // return (left.cost < right.cost); 64 | // } 65 | //}; 66 | 67 | struct server 68 | { 69 | vector serverNO;//一共net_node,bit来对染色体进行编码 70 | double bandwidths; 71 | int num_of_sercers; 72 | double fit;//适应值 73 | double rfit = 0;//相对的fit值,即所占的百分比 74 | double cfit = 0;//积累概率 75 | int cost = INT_MAX; 76 | 77 | bool operator<(const server &m) const 78 | { 79 | return fit < m.fit; 80 | } 81 | }; 82 | 83 | 84 | class MCMF 85 | { 86 | private: 87 | //某网络节点作为服务器时的最大提供带宽 88 | vector ServeAroundBandwidth;//序号为服务器所连的节点号,值为评估带宽 89 | //所有节点的评估带宽存储 90 | set AllNodeAroundBandwidth; 91 | int maxpoint; 92 | bool stop = false; 93 | vector > mapscost; 94 | vector > mapswidth; 95 | set SeverDirect;//消费节点必须直连的服务器节点信息 96 | int DirectBandwidth;//SeverDirect总评估带宽 97 | double TotalNeed;//所有消费节点总需求 98 | int SeverCost;//单台服务器成本 99 | int ServerTotalCost;//服务器总成本 100 | unsigned long maxServerNum;//最大服务器数,即消费节点数 101 | unsigned long minSeverNum;//最小服务器数 102 | vector > Nets; 103 | vector Consumers;//vector序号为消费节点编号 104 | unsigned long consumer_nodes, network_nodes;//链路数,消费节点数,网络节点数 105 | 106 | vector distance;/*各个节点到达源节点的距离*/ 107 | vector preVertex;/*各个节点的前一个节点*/ 108 | vector array; 109 | vector values; 110 | 111 | //消费节点连接的网络节点编号 112 | set ConsumerNum; 113 | //网络节点编号索引相连消费节点带宽 114 | map NodesLinkConsumerNeed; 115 | //网络节点编号索引相连消费节点序号 116 | map NodesLinkConsumerNO; 117 | 118 | 119 | //退火选择参数 120 | //随机删除一个服务器,小型数据 121 | double a1; 122 | //随机添加一个服务器,小型数据 123 | double a2; 124 | //随机按比例删除服务器,中大型数据 125 | double a3; 126 | //随机按比例增加服务器,中大型数据 127 | double a4; 128 | //优先删除所能提供带宽最小的服务器 129 | double a5; 130 | //优先添加所能提供带宽最大的服务器 131 | double a6; 132 | //完全产生新服务器 133 | double a7; 134 | //随机添加t1个服务器,再随机删除t2个服务器 135 | double a8; 136 | //添加一个最大服务器,再删除最小的服务器 137 | //a8~100 138 | 139 | public: 140 | vector > paths; 141 | 142 | MCMF(const vector &Consumers, const vector> &Nets, const int &SeverCost,const double &TotalNeed); 143 | 144 | void setConsumersAndNets(const vector &Consumers, const vector> &Nets); 145 | 146 | void setServers(const set &SeverNo); 147 | 148 | void setSeverCostAndTotalNeed(const int &SeverCost, const double &TotalNeed); 149 | 150 | //模拟退火产生新的服务器编号组合 151 | set 152 | getNewServe(const set &oldServe); 153 | 154 | 155 | void setServeAroundBandwidth(); 156 | 157 | set getSeverNo(); 158 | 159 | void mainFunction(); 160 | 161 | bool isenough(); 162 | 163 | void Dijkstra(); 164 | 165 | void decreaseAndPrintf(vector trace); 166 | 167 | void printvalues(); 168 | 169 | void setBestPath(vector> &tpaths);//输出标准答案格式 170 | 171 | string getBestPath(); 172 | 173 | //得到部署服务器的成本 174 | void setTotalServerCost(const set &v); 175 | 176 | int getLinksTotalCost(); 177 | 178 | int getServerTotalCost(); 179 | 180 | int getTotalCost(); 181 | 182 | int evaluateCost(const set &sever); 183 | 184 | void setSeverDirect(); 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | //遗传相关 198 | 199 | double StdFit; 200 | 201 | vector pro_server;//服务器编号集群未编码 202 | void setPro_server(const set &curSever, int x); 203 | 204 | int Max_Point;//二进制网络节点数 205 | 206 | // server popcurrent [PopulationSize]; // 初始种群规模 207 | vector popcurrent; // 初始种群 208 | 209 | vector popnext; // 更新后种群 210 | 211 | void init_popcurrent();//将十组Server转化为十组基因,进行种群的初始化 212 | 213 | //将个体二进制字节流转化为服务器编号,用于计算目标函数 214 | set getServerFromBit(const server &singlepopcurrent); 215 | 216 | 217 | //根据个体的适应度进行排序 218 | void SortAndChoosePopcurrent(int x);//选择操作 219 | 220 | // 基于概率分布的轮盘法选择 221 | void randompickup_new(); 222 | 223 | void crossover();//交叉操作 224 | 225 | void mutation();//突变 226 | 227 | 228 | double r8_uniform_ab(double a, double b, int &seed);//生成a~b之间均匀分布的数字 229 | 230 | set 231 | getNewGA(const set &oldServe); 232 | 233 | void evaluateNextFit(); 234 | 235 | int getNumOfServers(vector serverNO); 236 | 237 | int getbandwidthOfServers(vector serverNO); 238 | 239 | 240 | //遗传算法产生新的服务器编号组合 241 | set getGASeverNo(); 242 | }; 243 | 244 | 245 | #endif //CDN_MCMF_H 246 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cdn 解决最优网络流传输分配的服务器选点问题 2 | 3 | > 此项目可供参考解决相关网络流问题、运筹学选址规划问题以及物流分发问题 4 | 5 | ## 问题描述 6 | 7 | > 在给定结构的G省电信网络中,为了视频内容快速低成本的传送到每个住户小区,需要在这个给定网络结构中选择一些网络节点附近放置视频内容存储服务器。需要解决的问题是:在满足所有的住户小区视频播放需求的基本前提下,如何选择视频内容存储服务器放置位置,使得成本最小。 8 | 9 | ## 问题模型 10 | 11 | > 网络结构模型:给定一个由若干网络节点(例如路由器、交换机)构成的网络结构无向图,每个节点至少与另外一个节点通过网络链路相连(网络链路特指两个网络节点之间直接相连的网络通路,中间没有其他网络节点,相当于无向图中的一条边),一个节点可以将收到的数据通过网络链路传输给相连的另一个节点。每条链路的网络总带宽不同(例如某条链路的总带宽为10Gbps)。而每条链路承载的视频传输需要按照占用带宽的多少收取对应网络租用费,每条链路的单位租用费均不同(例如某条链路的租用费为1,000元/Gbps,即1K/Gbps)。某条链路上被占用的带宽总和不得超过该链路的总带宽。 12 | 13 | > 消费节点:给定的网络结构中有部分网络节点直接连接到小区住户的网络,每个小区住户网络在这个给定的网络结构图中呈现为一个消费节点,不同消费节点的视频带宽消耗需求不同。 14 | 15 | > 视频内容服务器:视频内容服务器存放视频内容(如:电影影片、电视剧等),视频内容服务器的视频数据流可以经由网络节点与链路构成的网络路径流向消费节点,视频内容服务器的输出能力没有上限,可以服务多个消费节点,一个消费节点也可以同时从多台视频内容服务器获取视频流。部署一台视频内容服务器需要费用成本(例如300,000元/台,即300K/台),所有服务器的成本均相同。 16 | 17 | ## 需求 18 | 19 | > 从网络结构模型中选择一部分网络节点,在其上/附近一对一的部署视频内容服务器,视频内容服务器与对应的这个节点直连,与对应的这个网络节点之间的通信没有带宽限制、也没有通信成本。提供的部署方案需要使得视频流从视频内容服务器经过一些网络节点和链路到达消费节点,并满足所有消费节点的视频带宽消耗需求。 20 | 21 | > 在满足所有消费节点视频带宽消耗需求的前提下,使得耗费的总成本(视频内容服务器部署成本+带宽租用成本)最低。部署方案不仅需要包括部视频内容服务器的节点位置,而且还要包括每个消费节点与所有视频内容服务器之间的网络路径以及路径上占用的带宽。  22 | 23 | 24 | # 整体思路: 25 | 26 | * 先解决CDN位置确定时的最小费用最大流问题 27 | 28 | > 使用MCMF(最小费用最大流)算法,加入超级源点和超级汇点的思想:超级源点连接设定好的CDN(为了方便,接下来服务器都会被简称为CDN),超级汇点连接所有的消费节点所连接的网络节点,并且保证所有消费节点连接到超级汇点的链路带宽即为其带宽需求。至此,当确定某几个节点为CDN时,可以求出最大流为且只能为固定值时的最小费用问题,所以接下来我们只需要想方法来确定CDN位置。 29 | 30 | 31 | * 先模拟退火,然后再对优解做遗传进化 32 | > 采用从直连解法为种子,进行模拟退火,启发式搜索,在退火过程中加大抖动力度,让搜索范围更全局,而非陷入某个局部最优。之后,将模拟退火的解作为祖先,进行交叉变异,遗传进化,快速迭代出更优秀的解。 33 | 34 | 35 | ## 数据结构设计 36 | ```C++ 37 | 38 | //某网络节点作为服务器时的最大提供带宽 39 | //序号为服务器所连的节点号,值为评估带宽 40 | vector ServeAroundBandwidth; 41 | 42 | //所有节点的评估带宽存储 43 | //插入时,级按带宽权重排序,以便后续退火出优解提供更好的候选节点 44 | set AllNodeAroundBandwidth; 45 | 46 | //消费节点连接的网络节点编号 47 | set ConsumerNum; 48 | 49 | //网络节点编号索引相连消费节点带宽 50 | map NodesLinkConsumerNeed; 51 | 52 | //网络节点编号索引相连消费节点序号 53 | map NodesLinkConsumerNO; 54 | 55 | struct SeverNoAndAroundBandwidth 56 | { 57 | int ServerNo; 58 | int ServeAroundBandwidth; 59 | }; 60 | 61 | struct server 62 | { 63 | vector serverNO;//一共net_node,bit来对染色体进行编码 64 | double bandwidths; 65 | int num_of_sercers; 66 | double fit;//适应值 67 | double rfit = 0;//相对的fit值,即所占的百分比 68 | double cfit = 0;//积累概率 69 | int cost = INT_MAX; 70 | 71 | bool operator<(const server &m) const 72 | { 73 | return fit < m.fit; 74 | } 75 | }; 76 | 77 | struct SeverSetAndCost 78 | { 79 | set SetSeverNO;//服务器编号集合 80 | int cost;//对应的成本 81 | }; 82 | 83 | struct Bandwidth_From_Small_To_Big 84 | { 85 | bool operator()(const SeverNoAndAroundBandwidth &left, const SeverNoAndAroundBandwidth &right) const 86 | { 87 | return (left.ServeAroundBandwidth < right.ServeAroundBandwidth); 88 | } 89 | }; 90 | 91 | 92 | //链路信息(双向) 93 | struct LinkInfo 94 | { 95 | int total_bandwidth = 0; 96 | int network_hire = INT_MAX; 97 | }; 98 | 99 | //消费节点信息结构体 100 | struct ResumeInfo 101 | { 102 | int node_NO;//消费节点连接的网络节点编号 103 | int need_bandwidth;//需求带宽 104 | }; 105 | 106 | 107 | ``` 108 | 109 | 110 | ## 模拟退火算法流程 111 | ![模拟退火](./docs/模拟退火算法流程.jpeg) 112 | 113 | ## 模拟退火数学模型 114 | 115 | > 根据Metropolis准则,粒子在温度T时趋于平衡的概率为exp(-ΔE/(kT)),其中E为温度T时的内能,ΔE为其改变数,k为Boltzmann常数。Metropolis准则常表示为 116 | 117 | ![Metropolis](./docs/Metropolis.png) 118 | 119 | >   Metropolis准则表明,在温度为T时,出现能量差为dE的降温的概率为P(dE),表示为:P(dE) = exp( dE/(kT) )。其中k是一个常数,exp表示自然指数,且dE<0。所以P和T正相关。这条公式就表示:温度越高,出现一次能量差为dE的降温的概率就越大;温度越低,则出现降温的概率就越小。又由于dE总是小于0(因为退火的过程是温度逐渐下降的过程),因此dE/kT < 0 ,所以P(dE)的函数取值范围是(0,1) 。随着温度T的降低,P(dE)会逐渐降低。
  我们将一次向较差解的移动看做一次温度跳变过程,我们以概率P(dE)来接受这样的移动。也就是说,在用固体退火模拟组合优化问题,将内能E模拟为目标函数值 f,温度T演化成控制参数 t,即得到解组合优化问题的模拟退火演算法:由初始解 i 和控制参数初值 t 开始,对当前解重复“产生新解→计算目标函数差→接受或丢弃”的迭代,并逐步衰减 t 值,算法终止时的当前解即为所得近似最优解,这是基于蒙特卡罗迭代求解法的一种启发式随机搜索过程。退火过程由冷却进度表(Cooling Schedule)控制,包括控制参数的初值 t 及其衰减因子Δt 、每个 t 值时的迭代次数L和停止条件S。 120 | 121 | 122 | ## 退火策略 123 | 124 | * 1、先对数据量(节点数量)进行分类,分为大、中、小三类 125 | * 2、各个类型下,进行不同的退火策略,具体策略及其执行概率见下方 126 | ```C++ 127 | if (consumer_nodes > 300) 128 | { 129 | //大型数据 130 | //随机删除一个服务器,小型数据 131 | a1 = 35; 132 | //随机添加一个服务器,小型数据 133 | a2 = 35; 134 | //随机按比例删除服务器,中大型数据 135 | a3 = 100; 136 | //随机按比例增加服务器,中大型数据 137 | a4 = 100; 138 | //优先删除所能提供带宽最小的服务器 139 | a5 = 100; 140 | //优先添加所能提供带宽最大的服务器 141 | a6 = 100; 142 | //完全产生新服务器 143 | a7 = 100; 144 | //随机添加t1个服务器,再随机删除t2个服务器 145 | a8 = 100; 146 | //添加一个最大服务器,再删除最小的服务器 147 | //a8~100 148 | 149 | } else if (consumer_nodes > 100) 150 | { 151 | //中型数据 152 | //随机删除一个服务器,小型数据 153 | a1 = 70; 154 | //随机添加一个服务器,小型数据 155 | a2 = 100; 156 | //随机按比例删除服务器,中大型数据 157 | a3 = 100; 158 | //随机按比例增加服务器,中大型数据 159 | a4 = 100; 160 | //优先删除所能提供带宽最小的服务器 161 | a5 = 100; 162 | //优先添加所能提供带宽最大的服务器 163 | a6 = 100; 164 | //完全产生新服务器 165 | a7 = 100; 166 | //随机添加t1个服务器,再随机删除t2个服务器 167 | a8 = 100; 168 | //添加一个最大服务器,再删除最小的服务器 169 | //a8~100 170 | } else 171 | { 172 | //小型数据 173 | //随机删除一个服务器,小型数据 174 | a1 = 70; 175 | //随机添加一个服务器,小型数据 176 | a2 = 100; 177 | //随机按比例删除服务器,中大型数据 178 | a3 = 100; 179 | //随机按比例增加服务器,中大型数据 180 | a4 = 100; 181 | //优先删除所能提供带宽最小的服务器 182 | a5 = 100; 183 | //优先添加所能提供带宽最大的服务器 184 | a6 = 100; 185 | //完全产生新服务器 186 | a7 = 100; 187 | //随机添加t1个服务器,再随机删除t2个服务器 188 | a8 = 100; 189 | //添加一个最大服务器,再删除最小的服务器 190 | //a8~100 191 | } 192 | ``` 193 | 194 | ## 退火后的优化解进行遗传进化,快速出解 195 | 196 | ![GA](./docs/GA.png) 197 | 198 | 199 | ## 运行文档 200 | ``` 201 | 1、整体指引: 202 | 1)使用一键式脚本编译、链接并打包压缩,如果编译失败请自行解决编译问题; 203 | 2)如果编译成功会在bin/目录下生成可执行二进制文件"cdn"; 204 | 3)使用如下格式调用并调试程序"./cdn /xxx/topo.txt /xxx/result.txt",其中topo.txt是输入文件(用例文件)位置,result.txt是输出文件位置; 205 | 206 | 207 | 2、cdn目录结构: 208 | cdn/ 209 | ├── bin/ 可执行二进制文件目录,shell脚本在编译前删除此目录并重新创建此目录,故没有此目录不会影响脚本运行 210 | ├── build/ 构建目录,shell脚本在编译前删除此目录并重新创建此目录,故没有此目录不会影响脚本运行 211 | ├── cdn/ 代码目录 212 | │ ├── lib/ lib头文件目录 213 | │ │ ├── lib_io.h 读写文件的头文件 214 | │ │ └── lib_time.h 打印时间的头文件 215 | │ ├── CMakeLists.txt cmake 216 | │ ├── cdn.cpp main函数源文件 217 | │ ├── io.cpp 提供读写文件等功能的源文件 218 | │ ├── MCMF.cpp 算法主要功能详细实现类的源文件 219 | │ ├── MCMF.h 算法主要功能详细实现类的头文件 220 | │ ├── global.cpp 全局中断信号源文件 221 | │ ├── global.h 全局中断信号头文件 222 | │ ├── deploy.cpp 算法主要运行框架的源文件 223 | │ └── deploy.h 算法主要运行框架的头文件 224 | ├── build.sh 编译、链接、打包批处理脚本 225 | ├── case_example/ 测试用例 226 | └── readme.md 你正在看的文件 227 | 228 | 3、build.sh脚本说明: 229 | 执行此脚本可以一键编译、链接、打包。如果编译和链接正确,会在bin/下生成cdn二进制文件,可以本地自测验证。同时会在当前目录下生成cdn.tar.gz。 230 | 注意: 231 | 1)shell脚本会删除bin/和build/目录,以及这两个目录下的所有文件和目录。请不要在此保存你的任何文档; 232 | 2)如果想使用shell脚本一键功能,请保持根cdn/目录下所有内容的完整,请不要修改任何目录名和文件名,并保持各目录和文件的位置关系不变。 233 | 234 | 4、手工操作说明:(非必须。如果选择使用shell脚本构建,可忽略本节内容) 235 | 1)在根cdn/目录下创建build_private/目录,并在build_private/下编写makefile文件; 236 | 2)进入build_private/,执行make完成编译和链接; 237 | 238 | 注意: 239 | 1)不要在build/下保存你的makefile文件,一旦调用batch.sh将会删除你的makefile文件; 240 | 2)生成压缩包时,应确保将代码源文件置于压缩包的最外层,即打开压缩包无需进入任何目录即可看全部源文件,否则可能编译失败。 241 | 242 | 5、运行读取问题文件位置 243 | 1)读取问题文件位置: cdn/cdn/cdn.cpp 244 | 示范: char *topo_file = (char *) "XXX/case_example/1/0/case8.txt"; 245 | 2)解决方案输出文件位置: cdn/cdn/cdn.cpp 246 | 示范: char *result_file = (char *) "XXX/YYY.txt"; 247 | 248 | 249 | ``` -------------------------------------------------------------------------------- /cdn/deploy.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "deploy.h" 3 | #include "MCMF.h" 4 | 5 | using namespace std; 6 | 7 | //C++整数规划+模拟退火方案 8 | 9 | 10 | //通过调用alarm来设置计时器,然后继续做别的事情。当计时器计时到0时,信号发送,处理函数被调用。 11 | 12 | void timer(int sig) 13 | { 14 | isExit = 0; 15 | } 16 | 17 | void deploy_server(char *topo[MAX_EDGE_NUM], int line_num, char *filename) 18 | { 19 | 20 | int TotalNeed;//所有消费节点总需求 21 | int SeverCost; 22 | stringstream read(topo[0]); 23 | unsigned long links, consumer_nodes, network_nodes;//链路数,消费节点数,网络节点数 24 | read >> network_nodes >> links >> consumer_nodes; 25 | //单台服务器成本 26 | SeverCost = atoi(topo[2]); 27 | 28 | vector> Nets(network_nodes, vector(network_nodes)); 29 | for (unsigned long i = 4; i < 4 + links; ++i) 30 | { 31 | int start_node, end_node; 32 | int total_bandwidth, network_hire; 33 | read.str(""); 34 | read << topo[i]; 35 | read >> start_node >> end_node >> total_bandwidth >> network_hire; 36 | Nets[start_node][end_node].total_bandwidth = total_bandwidth; 37 | Nets[start_node][end_node].network_hire = network_hire; 38 | Nets[end_node][start_node].total_bandwidth = total_bandwidth; 39 | Nets[end_node][start_node].network_hire = network_hire; 40 | } 41 | 42 | vector Consumers(consumer_nodes);//vector序号为消费节点编号 43 | TotalNeed = 0;//消费节点总需求 44 | for (unsigned long j = 5 + links; j < 5 + links + consumer_nodes; ++j) 45 | { 46 | int num, node_NO, need_bandwidth; 47 | read.str(""); 48 | read << topo[j]; 49 | read >> num >> node_NO >> need_bandwidth; 50 | Consumers[num].need_bandwidth = need_bandwidth; 51 | Consumers[num].node_NO = node_NO; 52 | TotalNeed += need_bandwidth; 53 | } 54 | 55 | if (links > 4000) 56 | { 57 | //TODO:直连方案(大数据直接输出直连) 58 | read.str(""); 59 | stringstream &results = read; 60 | results << consumer_nodes << "\n"; 61 | for (unsigned long k = 0; k < consumer_nodes; ++k) 62 | { 63 | results << "\n" << Consumers[k].node_NO << " " << k << " " << Consumers[k].need_bandwidth; 64 | } 65 | const string &strDirect = results.str(); 66 | 67 | char *topo_file = (char *) strDirect.c_str(); 68 | write_result(topo_file, filename); 69 | } else 70 | { 71 | 72 | //TODO:接入msmf类 73 | //初始化 74 | MCMF mcmf(Consumers, Nets, SeverCost, TotalNeed); 75 | 76 | 77 | /* //传入服务器编号 78 | auto curSeverNo=mcmf.getSeverNo(); 79 | 80 | mcmf.setServers(curSeverNo); 81 | 82 | mcmf.mainFunction();//主方法 83 | 84 | mcmf.getBestPath();//输出标准格式最优路径 85 | // PRINT("%lf\n", mcmf.getTotalCost()); 86 | cout << endl << mcmf.getTotalCost() << endl; 87 | auto newSever = curSeverNo; 88 | for (int l = 0; l < 1000; ++l) 89 | { 90 | newSever = mcmf.getNewServe(curSeverNo); 91 | double dE = mcmf.evaluateCost(newSever) - mcmf.evaluateCost(curSeverNo); 92 | curSeverNo = newSever; 93 | cout< 2000) 105 | { 106 | //执行定时器函数 107 | signal(SIGALRM, timer); 108 | alarm(86); //定时80s 109 | T = 1000; //初始温度 110 | EPS = 1e-9; //终止温度 111 | DELTA = 0.98; //温度衰减率 112 | LIMIT = 10; //概率选择上限 113 | OLOOP = 20000; //外循环次数 114 | ILOOP = 1000; //内循环次数 115 | p0 = 1.0; 116 | } else if (links > 1000) 117 | { 118 | //执行定时器函数 119 | signal(SIGALRM, timer); 120 | alarm(89); //定时80s 121 | T = 1000; //初始温度 122 | EPS = 1e-9; //终止温度 123 | DELTA = 0.98; //温度衰减率 124 | LIMIT = 8; //概率选择上限 125 | OLOOP = 3000; //外循环次数 126 | ILOOP = 1000; //内循环次数 127 | p0 = 1; 128 | } else 129 | { 130 | //执行定时器函数 131 | signal(SIGALRM, timer); 132 | alarm(88); //定时80s 133 | // T = 650; //初始温度 134 | // EPS = 1e-9; //终止温度 135 | // DELTA = 0.95; //温度衰减率 136 | // LIMIT = 20; //概率选择上限 137 | // OLOOP = 300; //外循环次数 138 | // ILOOP = 400; //内循环次数 139 | // p0=1.22; 140 | T = 1000; //初始温度 141 | EPS = 1e-9; //终止温度 142 | DELTA = 0.98; //温度衰减率 143 | LIMIT = 40; //概率选择上限 144 | OLOOP = 500; //外循环次数 145 | ILOOP = 450; //内循环次数 146 | p0 = 0.83; 147 | } 148 | 149 | double t = T; 150 | int P_L = 0; 151 | int P_F = 0; 152 | srand((unsigned int) time(NULL)); 153 | 154 | 155 | //TODO:遗传进化 156 | /* auto curSeverNo = mcmf.getSeverNo(); 157 | int bestCost; 158 | mcmf.setPro_server(curSeverNo, 10); 159 | mcmf.init_popcurrent(); 160 | while (isExit) 161 | { 162 | mcmf.randompickup_new(); 163 | mcmf.crossover(); 164 | mcmf.mutation(); 165 | //算适应度 166 | mcmf.evaluateNextFit(); 167 | mcmf.SortAndChoosePopcurrent(10); 168 | bestCost = mcmf.popcurrent[0].cost; 169 | printf("\n总成本:%d/%d\n", bestCost, 108000); 170 | } 171 | bestCost = mcmf.popcurrent[0].cost; 172 | auto bestPath = mcmf.paths; 173 | mcmf.setBestPath(bestPath); 174 | printf("\n%s\n", mcmf.getBestPath().c_str());//输出标准格式最优路径 175 | printf("\n总成本:%d/%d\n", bestCost, 108000);*/ 176 | 177 | 178 | //TODO:模拟退火 179 | auto curSeverNo = mcmf.getSeverNo(); 180 | auto newSever = curSeverNo; 181 | 182 | auto bestSever1 = curSeverNo;//局部最优 183 | // auto bestSever2 = curSeverNo;//全局最优 184 | int bestCost = mcmf.evaluateCost(curSeverNo); 185 | int maxCost = bestCost; 186 | int curCost = bestCost;//当前的费用 187 | auto bestPath = mcmf.paths;//保存最优路径 188 | 189 | while (isExit) //外循环,主要更新参数t,模拟退火过程 190 | { 191 | // cout<<"==========================P_F:"< rd && exp(dE / t) < p0) 217 | if (exp(-dE / t) > rd && exp(-dE / t) > p0) 218 | //如果找到比当前更差的解,以一定概率接受该解,并且这个概率会越来越小 219 | { 220 | curSeverNo = newSever; 221 | curCost = newCost; 222 | // cout << "BadCost=" << curCost << endl; 223 | } 224 | P_L++; 225 | // cout << " P_L=" << P_L << endl; 226 | } 227 | if (P_L > LIMIT) 228 | { 229 | P_F++; 230 | P_L = 0;//TODO:是否要加? 231 | break; 232 | } 233 | } 234 | if (P_F > OLOOP || t < EPS) 235 | break; 236 | t *= DELTA; 237 | // cout<<"========================="<