diff --git a/documentation/fast_fourier_transform.md b/documentation/fast_fourier_transform.md new file mode 100644 index 00000000..c51daa92 --- /dev/null +++ b/documentation/fast_fourier_transform.md @@ -0,0 +1,29 @@ +# Fast Fourier Transform (FFT) + +This file documents the recursive Cooley-Tukey FFT implementation added to `R/mathematics/fast_fourier_transform.r`. + +## Description + +The `fft_recursive` function computes the discrete Fourier transform (DFT) of a numeric or complex vector using a divide-and-conquer Cooley-Tukey algorithm. If the input length is not a power of two, it is zero-padded to the next power of two. + +## Usage + +In an R session: + +source('mathematics/fast_fourier_transform.r') +fft_recursive(c(0, 1, 2, 3)) + +From the command line with Rscript: + +Rscript -e "source('R/mathematics/fast_fourier_transform.r'); print(fft_recursive(c(0,1,2,3)))" + +## Complexity + +Time complexity: O(n log n) for inputs with length a power of two; otherwise dominated by padding to next power of two. + +Space complexity: O(n) additional space for recursive calls. + +## Notes + +- The function returns a complex vector of the same length (after padding) as the input. +- This implementation is primarily educational; production code should prefer the optimized `fft` function available in base R. diff --git a/documentation/hamiltonian_path.md b/documentation/hamiltonian_path.md new file mode 100644 index 00000000..9f5a7a37 --- /dev/null +++ b/documentation/hamiltonian_path.md @@ -0,0 +1,27 @@ +# Hamiltonian Path (Backtracking) + +This document describes the Hamiltonian Path backtracking implementation in `R/graph_algorithms/hamiltonian_path.r`. + +## Description + +The `hamiltonianPath` function searches for a Hamiltonian Path in an undirected graph represented by an adjacency matrix. It uses backtracking to attempt to build a path that visits every vertex exactly once. + +## Usage + +In an R session: + +source('graph_algorithms/hamiltonian_path.r') + +From command line using Rscript: + +Rscript -e "source('R/graph_algorithms/hamiltonian_path.r')" + +## Complexity + +- Time complexity: O(n!) in the worst case (backtracking over permutations). +- Space complexity: O(n) for path storage and recursion. + +## Notes + +- The implementation assumes an undirected graph given as an adjacency matrix with 0/1 entries. +- For production use on larger graphs, consider heuristics or approximation algorithms; the problem is NP-complete. diff --git a/graph_algorithms/hamiltonian_path.r b/graph_algorithms/hamiltonian_path.r new file mode 100644 index 00000000..2d3da356 --- /dev/null +++ b/graph_algorithms/hamiltonian_path.r @@ -0,0 +1,83 @@ +# Hamiltonian Path (Backtracking) +# +# This implementation searches for a Hamiltonian Path in an undirected graph +# represented by an adjacency matrix. It uses backtracking to try all possible +# vertex sequences. The implementation follows the style used in other +# algorithms in the `R/graph_algorithms` folder. +# +# Time Complexity: O(n!) in the worst case (backtracking over permutations) +# Space Complexity: O(n) for the path and recursion stack +# +# Input: adjacency matrix `graph` (n x n) +# Output: prints a Hamiltonian path if found and returns TRUE, otherwise prints +# a message and returns FALSE + +# Function to check if vertex v can be added to path at position pos +isSafe <- function(v, graph, path, pos) { + # Check adjacency between current vertex and previous vertex + if (graph[path[pos - 1], v] == 0) + return(FALSE) + + # Check if vertex is already in path + if (v %in% path) + return(FALSE) + + return(TRUE) +} + +# Recursive function to find Hamiltonian path +hamiltonianUtil <- function(graph, path, pos) { + n <- nrow(graph) + + # Base case: if all vertices are included in the path + if (pos > n) + return(TRUE) + + for (v in 1:n) { + if (isSafe(v, graph, path, pos)) { + path[pos] <- v + + if (hamiltonianUtil(graph, path, pos + 1)) + return(TRUE) + + # Backtrack + path[pos] <- -1 + } + } + return(FALSE) +} + +# Main function to find Hamiltonian path +hamiltonianPath <- function(graph) { + n <- nrow(graph) + + for (start in 1:n) { + path <- rep(-1, n) + path[1] <- start + + if (hamiltonianUtil(graph, path, 2)) { + cat("Hamiltonian Path found:\n") + print(path) + return(TRUE) + } + } + + cat("No Hamiltonian Path found.\n") + return(FALSE) +} + +# Example usage and test +cat("=== Hamiltonian Path (Backtracking) ===\n") + +graph <- matrix(c( + 0, 1, 1, 0, + 1, 0, 1, 1, + 1, 1, 0, 1, + 0, 1, 1, 0 +), nrow = 4, byrow = TRUE) + +cat("Adjacency matrix:\n") +print(graph) + +cat("\nSearching for Hamiltonian Path...\n") +hamiltonianPath(graph) diff --git a/mathematics/fast_fourier_transform.r b/mathematics/fast_fourier_transform.r new file mode 100644 index 00000000..0ce03f96 --- /dev/null +++ b/mathematics/fast_fourier_transform.r @@ -0,0 +1,53 @@ +# Fast Fourier Transform (Cooley-Tukey recursive implementation) +# +# This implementation accepts a numeric or complex vector and returns +# its discrete Fourier transform as a complex vector. If the input length +# is not a power of two, the vector is zero-padded to the next power of two. +# +# Usage: +# source('mathematics/fast_fourier_transform.r') +# x <- c(0,1,2,3) +# fft_result <- fft_recursive(x) +# print(fft_result) + +next_power_of_two <- function(n) { + if (n <= 0) return(1) + p <- 1 + while (p < n) p <- p * 2 + p +} + +fft_recursive <- function(x) { + # Ensure input is complex + x <- as.complex(x) + N <- length(x) + + # Pad to next power of two if necessary + M <- next_power_of_two(N) + if (M != N) { + x <- c(x, rep(0+0i, M - N)) + N <- M + } + + if (N == 1) return(x) + + even <- fft_recursive(x[seq(1, N, by = 2)]) + odd <- fft_recursive(x[seq(2, N, by = 2)]) + + factor <- exp(-2i * pi * (0:(N/2 - 1)) / N) + T <- factor * odd + + c(even + T, even - T) +} + +# Example usage when run directly with Rscript +if (identical(Sys.getenv("R_SCRIPT_NAME"), "") && interactive()) { + # Running in interactive R session - show sample + x <- c(0, 1, 2, 3) + cat("Input:\n") + print(x) + cat("FFT result:\n") + print(fft_recursive(x)) +} + +# When running via Rscript, users can call: Rscript -e "source('R/mathematics/fast_fourier_transform.r'); print(fft_recursive(c(0,1,2,3)))"