diff --git a/dynamic_programming/kadane's_algo.r b/dynamic_programming/kadane's_algo.r new file mode 100644 index 00000000..16b13a54 --- /dev/null +++ b/dynamic_programming/kadane's_algo.r @@ -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 diff --git a/graph_algorithms/edmonds_blossom.r b/graph_algorithms/edmonds_blossom.r new file mode 100644 index 00000000..88b96a9a --- /dev/null +++ b/graph_algorithms/edmonds_blossom.r @@ -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. +# ============================================== diff --git a/graph_algorithms/stoer_wagner.r b/graph_algorithms/stoer_wagner.r new file mode 100644 index 00000000..f6836595 --- /dev/null +++ b/graph_algorithms/stoer_wagner.r @@ -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. +# ============================================== diff --git a/machine_learning/cnn.r b/machine_learning/cnn.r new file mode 100644 index 00000000..5aa9d9e9 --- /dev/null +++ b/machine_learning/cnn.r @@ -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). +# ============================================== diff --git a/machine_learning/guassian_process.r b/machine_learning/guassian_process.r new file mode 100644 index 00000000..89b5f2eb --- /dev/null +++ b/machine_learning/guassian_process.r @@ -0,0 +1,62 @@ +# ============================================== +# Gaussian Process Regression (GP) +# ============================================== +# Algorithm: Non-parametric Bayesian regression using Gaussian Processes. +# Framework: R (kernlab package) +# +# Purpose: +# - Perform regression while providing uncertainty estimates. +# - Useful for small datasets and Bayesian optimization. +# +# Core Idea: +# - Define a prior over functions using a kernel (covariance) function. +# - Update the posterior distribution using observed data. +# - Predictions include mean and variance (uncertainty) for each point. +# +# Complexity: +# - Time: O(n^3) due to inversion of the kernel matrix +# - Space: O(n^2) for storing the kernel matrix +# +# Edge Cases / Notes: +# - Choice of kernel is critical for good performance. +# - Computationally heavy for large datasets; sparse approximations exist. +# - Great for uncertainty quantification in predictions. +# +# Typical Applications: +# - Bayesian optimization +# - Small-data regression tasks +# - Time-series forecasting with uncertainty estimates +# +# Reference: +# Rasmussen, C. E., & Williams, C. K. I. (2006). Gaussian Processes for Machine Learning. +# ============================================== + +# Load required library +suppressPackageStartupMessages(library(kernlab)) + +# Example Dataset (Synthetic) +set.seed(42) +x <- seq(-5, 5, length.out = 50) +y <- sin(x) + rnorm(length(x), sd = 0.2) + +# Define Gaussian Process Regression Model +gp_model <- gausspr( + x = as.matrix(x), y = y, + kernel = "rbfdot" # Radial Basis Function (RBF) kernel +) + +# Make Predictions +x_test <- seq(-6, 6, length.out = 100) +y_pred <- predict(gp_model, as.matrix(x_test), type = "response") + +# Plot Results +plot(x, y, main = "Gaussian Process Regression", xlab = "X", ylab = "Y", pch = 19) +lines(x_test, y_pred, col = "blue", lwd = 2) +legend("topright", legend = c("Observations", "GP Prediction"), col = c("black", "blue"), pch = c(19, NA), lty = c(NA, 1)) + +# ============================================== +# Note: +# - This script defines a Gaussian Process Regression model in R. +# - Can be applied to other regression datasets by replacing x and y. +# - For large datasets, consider sparse GP approximations. +# ==============================================