Spaces:
Sleeping
Sleeping
Download training_programs/126_two_sat.c from HideIron/compiler-env: direct link, hf CLI and curl.
- Browser
- Download file 4.99 kB
-
https://huggingface.co/spaces/HideIron/compiler-env/resolve/main/training_programs/126_two_sat.c
- Command line
-
hf download hf://spaces/HideIron/compiler-env/training_programs/126_two_sat.c
-
curl -L -o 126_two_sat.c https://huggingface.co/spaces/HideIron/compiler-env/resolve/main/training_programs/126_two_sat.c
4.99 kB
| // 2-SAT solver using strongly connected components (Kosaraju's algorithm) | |
| // Determines satisfiability of 2-CNF boolean formulas | |
| typedef struct { | |
| int **adj; | |
| int **rev_adj; | |
| int *adj_count; | |
| int *rev_adj_count; | |
| int num_nodes; | |
| } Graph; | |
| typedef struct { | |
| int *stack; | |
| int top; | |
| } Stack; | |
| void push(Stack *s, int val) { | |
| s->stack[++s->top] = val; | |
| } | |
| int pop(Stack *s) { | |
| return s->stack[s->top--]; | |
| } | |
| Graph* create_graph(int num_vars) { | |
| int num_nodes = 2 * num_vars; // Each variable has positive and negative literals | |
| Graph *g = (Graph*)malloc(sizeof(Graph)); | |
| g->adj = (int**)malloc(num_nodes * sizeof(int*)); | |
| g->rev_adj = (int**)malloc(num_nodes * sizeof(int*)); | |
| g->adj_count = (int*)calloc(num_nodes, sizeof(int)); | |
| g->rev_adj_count = (int*)calloc(num_nodes, sizeof(int)); | |
| for (int i = 0; i < num_nodes; i++) { | |
| g->adj[i] = (int*)malloc(MAX_CLAUSES * sizeof(int)); | |
| g->rev_adj[i] = (int*)malloc(MAX_CLAUSES * sizeof(int)); | |
| } | |
| g->num_nodes = num_nodes; | |
| return g; | |
| } | |
| void add_edge(Graph *g, int u, int v) { | |
| g->adj[u][g->adj_count[u]++] = v; | |
| g->rev_adj[v][g->rev_adj_count[v]++] = u; | |
| } | |
| void dfs1(Graph *g, int v, int *visited, Stack *finish_stack) { | |
| visited[v] = 1; | |
| for (int i = 0; i < g->adj_count[v]; i++) { | |
| int u = g->adj[v][i]; | |
| if (!visited[u]) { | |
| dfs1(g, u, visited, finish_stack); | |
| } | |
| } | |
| push(finish_stack, v); | |
| } | |
| void dfs2(Graph *g, int v, int *visited, int *scc_id, int scc_num) { | |
| visited[v] = 1; | |
| scc_id[v] = scc_num; | |
| for (int i = 0; i < g->rev_adj_count[v]; i++) { | |
| int u = g->rev_adj[v][i]; | |
| if (!visited[u]) { | |
| dfs2(g, u, visited, scc_id, scc_num); | |
| } | |
| } | |
| } | |
| int solve_2sat(Graph *g, int num_vars) { | |
| int *visited = (int*)calloc(g->num_nodes, sizeof(int)); | |
| Stack finish_stack; | |
| finish_stack.stack = (int*)malloc(g->num_nodes * sizeof(int)); | |
| finish_stack.top = -1; | |
| // First DFS on original graph | |
| for (int i = 0; i < g->num_nodes; i++) { | |
| if (!visited[i]) { | |
| dfs1(g, i, visited, &finish_stack); | |
| } | |
| } | |
| // Second DFS on reversed graph | |
| memset(visited, 0, g->num_nodes * sizeof(int)); | |
| int *scc_id = (int*)malloc(g->num_nodes * sizeof(int)); | |
| int scc_num = 0; | |
| while (finish_stack.top >= 0) { | |
| int v = pop(&finish_stack); | |
| if (!visited[v]) { | |
| dfs2(g, v, visited, scc_id, scc_num); | |
| scc_num++; | |
| } | |
| } | |
| // Check if x and ~x are in same SCC | |
| int satisfiable = 1; | |
| for (int i = 0; i < num_vars; i++) { | |
| if (scc_id[2*i] == scc_id[2*i + 1]) { | |
| satisfiable = 0; | |
| break; | |
| } | |
| } | |
| free(visited); | |
| free(scc_id); | |
| free(finish_stack.stack); | |
| return satisfiable; | |
| } | |
| int main() { | |
| int num_vars = 200; | |
| int num_clauses = 500; | |
| unsigned int seed = 42; | |
| clock_t start = clock(); | |
| int satisfiable_count = 0; | |
| int total_tests = 100; | |
| for (int test = 0; test < total_tests; test++) { | |
| Graph *g = create_graph(num_vars); | |
| // Generate random 2-SAT clauses | |
| for (int i = 0; i < num_clauses; i++) { | |
| seed = seed * 1103515245 + 12345; | |
| int var1 = seed % num_vars; | |
| seed = seed * 1103515245 + 12345; | |
| int var2 = seed % num_vars; | |
| seed = seed * 1103515245 + 12345; | |
| int neg1 = seed % 2; | |
| seed = seed * 1103515245 + 12345; | |
| int neg2 = seed % 2; | |
| // Clause: (lit1 OR lit2) | |
| // Implications: ~lit1 => lit2, ~lit2 => lit1 | |
| int lit1 = 2 * var1 + neg1; | |
| int lit2 = 2 * var2 + neg2; | |
| int not_lit1 = 2 * var1 + (1 - neg1); | |
| int not_lit2 = 2 * var2 + (1 - neg2); | |
| add_edge(g, not_lit1, lit2); | |
| add_edge(g, not_lit2, lit1); | |
| } | |
| if (solve_2sat(g, num_vars)) { | |
| satisfiable_count++; | |
| } | |
| // Free graph | |
| for (int i = 0; i < g->num_nodes; i++) { | |
| free(g->adj[i]); | |
| free(g->rev_adj[i]); | |
| } | |
| free(g->adj); | |
| free(g->rev_adj); | |
| free(g->adj_count); | |
| free(g->rev_adj_count); | |
| free(g); | |
| } | |
| clock_t end = clock(); | |
| double time_spent = (double)(end - start) / CLOCKS_PER_SEC; | |
| printf("2-SAT solver: vars=%d, clauses=%d, %d tests, %.6f seconds\n", | |
| num_vars, num_clauses, total_tests, time_spent); | |
| printf("Satisfiable: %d/%d\n", satisfiable_count, total_tests); | |
| return 0; | |
| } | |