-
-
Notifications
You must be signed in to change notification settings - Fork 342
Add edmonds blossom algo #238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AtharvaPatange
wants to merge
8
commits into
TheAlgorithms:master
Choose a base branch
from
AtharvaPatange:add-edmonds_blossom_algo
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 7 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
457a1f3
feat-kadane's algo
AtharvaPatange d51320b
k-Nearest Neighbors
AtharvaPatange 563abaa
Convolutional Neural Network
AtharvaPatange 5676cd6
Gaussian Process Regression
AtharvaPatange ddc4be2
Stoer-Wagner algorithm
AtharvaPatange 5efdac0
edmonds_blossom_algo
AtharvaPatange e5b5189
Update graph_algorithms/edmonds_blossom.r
AtharvaPatange 3c09e79
Merge branch 'master' into add-edmonds_blossom_algo
siriak File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| # Kadane's Algorithm in R | ||
| # | ||
| # Finds the contiguous subarray with the largest sum. | ||
| # Time Complexity: O(n) | ||
| # Space Complexity: O(1) (not counting output subarray) | ||
| # | ||
| # Applications: | ||
| # - Financial time series (max profit window) | ||
| # - Signal processing (max energy segment) | ||
| # - Pattern detection in sequences | ||
| # - As a subroutine in more complex DP/optimization tasks | ||
|
|
||
| kadane <- function(arr) { | ||
| #' Kadane's algorithm to find maximum subarray sum and its indices | ||
| #' @param arr: Numeric vector (can include negatives and positives) | ||
| #' @return: A list with fields: | ||
| #' max_sum - numeric: maximum subarray sum | ||
| #' start - integer: start index of the subarray (1-based), NA if empty input | ||
| #' end - integer: end index of the subarray (1-based), NA if empty input | ||
| #' subarray- numeric vector: the subarray that gives max_sum (empty if input empty) | ||
|
|
||
| n <- length(arr) | ||
|
|
||
| # Edge cases | ||
| if (n == 0) { | ||
| return(list( | ||
| max_sum = -Inf, | ||
| start = NA_integer_, | ||
| end = NA_integer_, | ||
| subarray = numeric(0) | ||
| )) | ||
| } | ||
|
|
||
| # Initialize with first element (handles all-negative arrays correctly) | ||
| max_ending_here <- arr[1] | ||
| max_so_far <- arr[1] | ||
| s <- 1 | ||
| start <- 1 | ||
| end <- 1 | ||
|
|
||
| if (n >= 2) { | ||
| for (i in 2:n) { | ||
| # If adding arr[i] to current segment is worse than starting new at arr[i] | ||
| if (max_ending_here + arr[i] < arr[i]) { | ||
| max_ending_here <- arr[i] | ||
| s <- i | ||
| } else { | ||
| max_ending_here <- max_ending_here + arr[i] | ||
| } | ||
|
|
||
| # Update best segment if needed | ||
| if (max_ending_here > max_so_far) { | ||
| max_so_far <- max_ending_here | ||
| start <- s | ||
| end <- i | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return(list( | ||
| max_sum = max_so_far, | ||
| start = as.integer(start), | ||
| end = as.integer(end), | ||
| subarray = arr[start:end] | ||
| )) | ||
| } | ||
|
|
||
| # Variant: Kadane that returns also when you want first-occurrence vs. any occurrence | ||
| kadane_first_occurrence <- function(arr) { | ||
| # exactly like kadane() but ties favor earlier segment (current code already does) | ||
| kadane(arr) | ||
| } | ||
|
|
||
| # Helper to pretty-print results | ||
| print_kadane_result <- function(res, arr_name="Array") { | ||
| cat("Input:", arr_name, "\n") | ||
| if (is.na(res$start)) { | ||
| cat("Result: empty input\n\n") | ||
| return(invisible(NULL)) | ||
| } | ||
| cat("Max Subarray Sum:", res$max_sum, "\n") | ||
| cat("Start Index:", res$start, " End Index:", res$end, "\n") | ||
| cat("Subarray:", paste(res$subarray, collapse = ", "), "\n\n") | ||
| } | ||
|
|
||
| # =========================== | ||
| # Example Usage & Testing | ||
| # =========================== | ||
| cat("=== Kadane's Algorithm Tests ===\n\n") | ||
|
|
||
| # Test 1: Mixed positive and negative | ||
| arr1 <- c(-2, 1, -3, 4, -1, 2, 1, -5, 4) | ||
| res1 <- kadane(arr1) | ||
| print_kadane_result(res1, "arr1 (mixed)") | ||
|
|
||
| # Test 2: All positive | ||
| arr2 <- c(2, 3, 1, 4) | ||
| res2 <- kadane(arr2) | ||
| print_kadane_result(res2, "arr2 (all positive)") | ||
|
|
||
| # Test 3: All negative | ||
| arr3 <- c(-8, -3, -6, -2, -5, -4) | ||
| res3 <- kadane(arr3) | ||
| print_kadane_result(res3, "arr3 (all negative)") | ||
|
|
||
| # Test 4: Single element | ||
| arr4 <- c(5) | ||
| res4 <- kadane(arr4) | ||
| print_kadane_result(res4, "arr4 (single element)") | ||
|
|
||
| # Test 5: Empty array | ||
| arr5 <- numeric(0) | ||
| res5 <- kadane(arr5) | ||
| print_kadane_result(res5, "arr5 (empty)") | ||
|
|
||
| # Test 6: Random large array - timing example | ||
| set.seed(123) | ||
| arr6 <- sample(-100:100, 100000, replace = TRUE) | ||
| start_time <- Sys.time() | ||
| res6 <- kadane(arr6) | ||
| end_time <- Sys.time() | ||
| print_kadane_result(res6, "arr6 (large random)") | ||
| cat("Elapsed time (seconds):", as.numeric(end_time - start_time, units = "secs"), "\n\n") | ||
|
|
||
| # Optional: function to get maximum circular subarray (Kadane + total sum trick) | ||
| kadane_circular <- function(arr) { | ||
| #' Finds max subarray sum for circular arrays (wrap-around allowed) | ||
| #' If all elements are negative, returns max element (non-wrap). | ||
| n <- length(arr) | ||
| if (n == 0) return(list(max_sum = -Inf, start = NA, end = NA, subarray = numeric(0))) | ||
|
|
||
| # Standard Kadane for non-circular max | ||
| normal <- kadane(arr)$max_sum | ||
|
|
||
| # If all negative, normal already is max element; circular logic would fail | ||
| if (all(arr <= 0)) { | ||
| return(list(max_sum = normal, start = which.max(arr), end = which.max(arr), subarray = arr[which.max(arr)])) | ||
| } | ||
|
|
||
| # Max wrap = total_sum - min_subarray_sum | ||
| total_sum <- sum(arr) | ||
|
|
||
| # Find minimum subarray using Kadane on inverted array | ||
| inverted <- -arr | ||
| min_sub_sum <- kadane(inverted)$max_sum # this is -min_subarray_sum | ||
| max_wrap <- total_sum + min_sub_sum # because min_sub_sum is negative of min subarray | ||
|
|
||
| if (max_wrap > normal) { | ||
| return(list(max_sum = max_wrap, start = NA, end = NA, subarray = NA)) # indices for wrap-around not computed here | ||
| } else { | ||
| return(list(max_sum = normal, start = kadane(arr)$start, end = kadane(arr)$end, subarray = kadane(arr)$subarray)) | ||
| } | ||
| } | ||
|
|
||
| # Example for circular | ||
| cat("=== Circular Kadane Example ===\n") | ||
| arrc <- c(8, -1, 3, 4) | ||
| res_circ <- kadane_circular(arrc) | ||
| cat("Input:", paste(arrc, collapse = ", "), "\n") | ||
| cat("Max circular subarray sum:", res_circ$max_sum, "\n\n") | ||
|
|
||
| # End of script | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # ============================================== | ||
| # Edmonds’ Blossom Algorithm | ||
| # ============================================== | ||
| # Algorithm: Maximum matching in general (non-bipartite) graphs. | ||
| # Framework: R (using igraph package) | ||
| # | ||
| # Purpose: | ||
| # - Compute the maximum matching in a general (non-bipartite) graph. | ||
| # - Finds the largest set of edges without common vertices. | ||
| # | ||
| # Core Idea: | ||
| # - Uses the Blossom algorithm to handle odd-length cycles (blossoms) in non-bipartite graphs. | ||
| # - Iteratively augments paths to find the maximum matching. | ||
| # | ||
| # Complexity: | ||
| # - Time: O(V^3) in general (V = number of vertices) | ||
| # - Space: O(V + E) for graph representation | ||
| # | ||
| # Edge Cases / Notes: | ||
| # - Works for both bipartite and non-bipartite graphs. | ||
| # - Handles odd-length cycles using the blossom contraction technique. | ||
| # | ||
| # Typical Applications: | ||
| # - Network pairing/matching problems | ||
| # - Job assignment and scheduling | ||
| # - Stable pairings in tournaments or projects | ||
| # | ||
| # Reference: | ||
| # Edmonds, J. (1965). Paths, trees, and flowers. Canadian Journal of Mathematics. | ||
| # ============================================== | ||
|
|
||
| # Load required library | ||
| suppressPackageStartupMessages(library(igraph)) | ||
|
|
||
| # Example Graph: Non-bipartite | ||
| edges <- c(1,2, 1,3, 2,4, 3,4, 4,5) | ||
| g <- graph(edges, directed = FALSE) | ||
|
|
||
| # Compute Maximum Matching | ||
| matching <- max_matching(g) # Use max_matching for general (non-bipartite) graphs | ||
| max_match_edges <- matching$matching | ||
|
|
||
| # Display Result | ||
| cat("Maximum matching edges:\n") | ||
| print(max_match_edges) | ||
|
|
||
| # ============================================== | ||
| # Note: | ||
| # - This script defines the Edmonds’ Blossom Algorithm in R using igraph. | ||
| # - Suitable for small to medium non-bipartite graphs. | ||
| # - For large graphs, performance may degrade due to cubic complexity. | ||
| # ============================================== |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # ============================================== | ||
| # Stoer-Wagner Algorithm | ||
| # ============================================== | ||
| # Algorithm: Global minimum cut in undirected weighted graphs. | ||
| # Framework: R (base R) | ||
| # | ||
| # Purpose: | ||
| # - Find the minimum cut in an undirected weighted graph. | ||
| # - Identifies the smallest set of edges whose removal disconnects the graph. | ||
| # | ||
| # Core Idea: | ||
| # - Repeatedly merge vertices while keeping track of the minimum cut value. | ||
| # - Uses a greedy approach to find minimum cuts iteratively. | ||
| # | ||
| # Complexity: | ||
| # - Time: O(V^3) for dense graphs (V = number of vertices) | ||
| # - Space: O(V^2) for adjacency/weight matrix | ||
| # | ||
| # Edge Cases / Notes: | ||
| # - Works for connected undirected weighted graphs. | ||
| # - Graph must be undirected; weights must be non-negative. | ||
| # - Returns the minimum cut weight and optionally the vertex partition. | ||
| # | ||
| # Typical Applications: | ||
| # - Network reliability analysis | ||
| # - Graph clustering and partitioning | ||
| # - Identifying critical edges in networks | ||
| # | ||
| # Reference: | ||
| # Stoer, M., & Wagner, F. (1997). A simple min-cut algorithm. Journal of the ACM. | ||
| # ============================================== | ||
|
|
||
| # Example Graph: Adjacency Matrix (Weighted Undirected Graph) | ||
| graph <- matrix(c( | ||
| 0, 3, 1, 3, | ||
| 3, 0, 2, 2, | ||
| 1, 2, 0, 4, | ||
| 3, 2, 4, 0 | ||
| ), nrow = 4, byrow = TRUE) | ||
|
|
||
| # Stoer-Wagner Minimum Cut Function | ||
| stoer_wagner <- function(graph) { | ||
| n <- nrow(graph) | ||
| vertices <- 1:n | ||
| min_cut <- Inf | ||
|
|
||
| while (length(vertices) > 1) { | ||
| used <- rep(FALSE, n) | ||
| weights <- rep(0, n) | ||
| prev <- NULL | ||
|
|
||
| for (i in 1:length(vertices)) { | ||
| sel <- which.max(weights * (!used)) | ||
| used[sel] <- TRUE | ||
| if (i == length(vertices)) { | ||
| cut_weight <- weights[sel] | ||
| if (cut_weight < min_cut) { | ||
| min_cut <- cut_weight | ||
| } | ||
| # Merge last two vertices | ||
| if (!is.null(prev)) { | ||
| graph[prev, ] <- graph[prev, ] + graph[sel, ] | ||
| graph[, prev] <- graph[prev, ] | ||
| vertices <- vertices[vertices != sel] | ||
| } | ||
| } | ||
| prev <- sel | ||
| # Update weights | ||
| weights <- weights + graph[sel, ] | ||
| } | ||
| } | ||
| return(min_cut) | ||
| } | ||
|
|
||
| # Compute Minimum Cut | ||
| min_cut_value <- stoer_wagner(graph) | ||
| cat("Minimum cut weight of the graph:", min_cut_value, "\n") | ||
|
|
||
| # ============================================== | ||
| # Note: | ||
| # - This script defines the Stoer-Wagner minimum cut algorithm in R. | ||
| # - Works with small to medium weighted undirected graphs. | ||
| # - Can be extended to return the vertex partition corresponding to the cut. | ||
| # ============================================== |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # ============================================== | ||
| # Convolutional Neural Network (CNN) | ||
| # ============================================== | ||
| # Algorithm: Deep learning model using convolutional, pooling, and dense layers. | ||
| # Framework: Keras (TensorFlow backend) | ||
| # | ||
| # Purpose: | ||
| # - Automatically extract spatial and hierarchical features from image data. | ||
| # - Commonly used for image classification, object detection, and visual recognition. | ||
| # | ||
| # Architecture Steps: | ||
| # 1. Convolution Layer: Extracts local spatial patterns using learnable filters. | ||
| # 2. Activation (ReLU): Adds non-linearity by thresholding at zero. | ||
| # 3. Pooling Layer: Reduces spatial dimensions (downsampling) while preserving features. | ||
| # 4. Flatten Layer: Converts 2D feature maps into 1D vector. | ||
| # 5. Dense Layers: Combines extracted features for classification. | ||
| # 6. Output Layer: Uses Softmax activation for class probabilities. | ||
| # | ||
| # Complexity: | ||
| # - Time: O(E × N × F × K²) where E=epochs, N=samples, F=filters, K=kernel size | ||
| # - Space: O(parameters + feature maps) | ||
| # | ||
| # Reference: | ||
| # LeCun et al., "Gradient-based learning applied to document recognition" (1998) | ||
| # https://yann.lecun.com/exdb/lenet/ | ||
| # | ||
| # ============================================== | ||
|
|
||
| # Load Required Library | ||
| suppressPackageStartupMessages(library(keras)) | ||
|
|
||
| # Define CNN Architecture (Algorithm Only) | ||
| cnn_model <- keras_model_sequential() %>% | ||
| layer_conv_2d( | ||
| filters = 32, kernel_size = c(3, 3), activation = "relu", | ||
| input_shape = c(28, 28, 1), padding = "same" | ||
| ) %>% | ||
| layer_max_pooling_2d(pool_size = c(2, 2)) %>% | ||
| layer_conv_2d( | ||
| filters = 64, kernel_size = c(3, 3), | ||
| activation = "relu", padding = "same" | ||
| ) %>% | ||
| layer_max_pooling_2d(pool_size = c(2, 2)) %>% | ||
| layer_flatten() %>% | ||
| layer_dense(units = 128, activation = "relu") %>% | ||
| layer_dense(units = 10, activation = "softmax") | ||
|
|
||
| # Display Model Summary | ||
| summary(cnn_model) | ||
|
|
||
| # ============================================== | ||
| # Note: | ||
| # - This script defines the CNN algorithm structure only. | ||
| # - You can compile and train it using model %>% compile() and model %>% fit() | ||
| # with any dataset (e.g., MNIST, CIFAR-10). | ||
| # ============================================== |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This algorithm is already implemented