206 lines
4.2 KiB
C
206 lines
4.2 KiB
C
#include "algorithms.h"
|
|
#include "benchmark.h"
|
|
#include "structs.h"
|
|
#include "render.h"
|
|
#include <SDL2/SDL.h>
|
|
#include <stdlib.h>
|
|
|
|
#define WINDOW_WIDTH 800
|
|
#define WINDOW_HEIGHT 600
|
|
|
|
static void print_usage(const char *prog)
|
|
{
|
|
fprintf(stderr,
|
|
"Usage:\n"
|
|
" %s -fig1|-fig2|-fig3|-fig4|-fig5\n"
|
|
" %s -b\n"
|
|
" %s <n> <p> <q> <clique|louvain|cbla>\n\n"
|
|
"Options:\n"
|
|
" -fig1 preset: n=20, p=0.9, q=0.25\n"
|
|
" -fig2 preset: n=50, p=0.7, q=0.15\n"
|
|
" -fig3 preset: n=100, p=0.5, q=0.05\n"
|
|
" -fig4 preset: n=200, p=0.2, q=0.02\n"
|
|
" -fig5 preset: n=500, p=0.01, q=0.00025\n"
|
|
" -b run benchmark\n"
|
|
" n number of nodes\n"
|
|
" p intra-group edge probability\n"
|
|
" q inter-group edge probability\n"
|
|
" algo clique | louvain | cbla\n",
|
|
prog, prog, prog);
|
|
}
|
|
|
|
typedef struct {
|
|
int n;
|
|
double p;
|
|
double q;
|
|
int seed;
|
|
int k;
|
|
VISUALIZATION_TYPE algo;
|
|
} run_config_t;
|
|
|
|
static int parse_algo(const char *s, VISUALIZATION_TYPE *out)
|
|
{
|
|
if (strcmp(s, "clique") == 0) {
|
|
*out = CLIQUE;
|
|
return 1;
|
|
} else if (strcmp(s, "louvain") == 0) {
|
|
*out = LOUVAIN;
|
|
return 1;
|
|
} else if (strcmp(s, "cbla") == 0) {
|
|
*out = CBLA;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int parse_fig(const char *arg, run_config_t *cfg)
|
|
{
|
|
if (strcmp(arg, "-fig1") == 0) {
|
|
cfg->n = 20;
|
|
cfg->p = 1.0;
|
|
cfg->q = 0.04;
|
|
cfg->k = 3;
|
|
cfg->seed = 122;
|
|
cfg->algo = CLIQUE;
|
|
return 1;
|
|
} else if (strcmp(arg, "-fig2") == 0) {
|
|
cfg->n = 20;
|
|
cfg->q = 1.0;
|
|
cfg->p = 0.04;
|
|
cfg->k = 3;
|
|
cfg->seed = 122;
|
|
cfg->algo = CLIQUE;
|
|
return 1;
|
|
} else if (strcmp(arg, "-fig3") == 0) {
|
|
cfg->n = 20;
|
|
cfg->p = 0.04;
|
|
cfg->q = 0.04;
|
|
cfg->k = 3;
|
|
cfg->seed = 122;
|
|
cfg->algo = CLIQUE;
|
|
return 1;
|
|
} else if (strcmp(arg, "-fig4") == 0) {
|
|
cfg->n = 20;
|
|
cfg->p = 0.8;
|
|
cfg->q = 0.10;
|
|
cfg->k = 0;
|
|
cfg->seed = 122;
|
|
cfg->algo = LOUVAIN;
|
|
return 1;
|
|
} else if (strcmp(arg, "-fig5") == 0) {
|
|
cfg->n = 20;
|
|
cfg->p = 0.8;
|
|
cfg->q = 0.10;
|
|
cfg->k = 3;
|
|
cfg->seed = 122;
|
|
cfg->algo = CBLA;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void run_sdl(run_config_t *cfg)
|
|
{
|
|
printf("[main] generating graph n=%d p=%.4f q=%.6f\n", cfg->n, cfg->p,
|
|
cfg->q);
|
|
|
|
graph_t *graph = generate_graph(cfg->n, cfg->p, cfg->q, cfg->seed);
|
|
if (!graph) {
|
|
fprintf(stderr, "[main] generate_graph failed\n");
|
|
return;
|
|
}
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
|
fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
|
|
free_graph(graph);
|
|
return;
|
|
}
|
|
SDL_Window *window =
|
|
SDL_CreateWindow("Graph Visualizer", SDL_WINDOWPOS_CENTERED,
|
|
SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH,
|
|
WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
|
|
|
|
SDL_Renderer *renderer = SDL_CreateRenderer(
|
|
window, -1,
|
|
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
|
|
|
render_graph(renderer, graph, cfg->algo, cfg->k);
|
|
|
|
// Event loop
|
|
SDL_Event e;
|
|
int running = 1;
|
|
while (running) {
|
|
while (SDL_PollEvent(&e)) {
|
|
if (e.type == SDL_QUIT)
|
|
running = 0;
|
|
if (e.type == SDL_KEYDOWN &&
|
|
e.key.keysym.sym == SDLK_ESCAPE)
|
|
running = 0;
|
|
// Re-render on window resize
|
|
if (e.type == SDL_WINDOWEVENT &&
|
|
e.window.event == SDL_WINDOWEVENT_RESIZED)
|
|
render_graph(renderer, graph, cfg->algo,
|
|
cfg->k);
|
|
}
|
|
SDL_Delay(16);
|
|
}
|
|
|
|
SDL_DestroyRenderer(renderer);
|
|
SDL_DestroyWindow(window);
|
|
SDL_Quit();
|
|
free_graph(graph);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc < 2) {
|
|
print_usage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp(argv[1], "-b") == 0) {
|
|
run_benchmark();
|
|
return 0;
|
|
}
|
|
|
|
run_config_t cfg = {
|
|
.n = 0, .p = 0, .q = 0, .seed = 42, .algo = CLIQUE
|
|
};
|
|
|
|
if (parse_fig(argv[1], &cfg)) {
|
|
// optionally override algo: ./graphe -fig3 louvain
|
|
if (argc >= 3 && !parse_algo(argv[2], &cfg.algo)) {
|
|
fprintf(stderr, "[main] unknown algo '%s'\n", argv[2]);
|
|
print_usage(argv[0]);
|
|
return 1;
|
|
}
|
|
run_sdl(&cfg);
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 5) {
|
|
print_usage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
cfg.n = atoi(argv[1]);
|
|
cfg.p = atof(argv[2]);
|
|
cfg.q = atof(argv[3]);
|
|
|
|
if (cfg.n <= 0 || cfg.p < 0 || cfg.p > 1 || cfg.q < 0 || cfg.q > 1) {
|
|
fprintf(stderr,
|
|
"[main] invalid arguments: n must be > 0, p and q in [0,1]\n");
|
|
return 1;
|
|
}
|
|
if (!parse_algo(argv[4], &cfg.algo)) {
|
|
fprintf(stderr, "[main] unknown algo '%s'\n", argv[4]);
|
|
print_usage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
run_sdl(&cfg);
|
|
return 0;
|
|
|
|
return 0;
|
|
}
|