Skip to content
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

Implemented Ternary Search Algorithm #24

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
## Searches
* [linear_search](/modules/searches/linear_search.f90)
* [recursive_linear_search](/modules/searches/recursive_linear_search.f90)
* [ternary_search](/modules/searches/ternary_search_module.f90)
## Sorts
* [bubble_sort](/modules/sorts/bubble_sort.f90)
* [recursive_bubble_sort](/modules/sorts/recursive_bubble_sort.f90)
Expand Down
20 changes: 20 additions & 0 deletions examples/searches/example_ternary_search_array_based.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
! Example Program: Array-based Ternary Search
! This program demonstrates how to use the array-based ternary search algorithm
! implemented in the `ternary_search` module to find a target element in a sorted array.

program example_ternary_search_array
use ternary_search
implicit none
integer :: result ! Holds the index of the found target
integer, dimension(10) :: arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] ! Sorted Test Array
integer :: target ! Target value to search for

target = 17
result = ternary_search_array(arr, target, 1, size(arr))

if (result /= -1) then
print *, "Target found at index:", result
else
print *, "Target not found."
end if
end program example_ternary_search_array
65 changes: 65 additions & 0 deletions examples/searches/example_ternary_search_function_based.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
! Example Program: Function-based Ternary Search for Minimum and Maximum
! This program demonstrates how to use the function-based ternary search algorithm
! from the `ternary_search` module to find the minimum and maximum of unimodal functions.

program ternary_search_function_based
use ternary_search
implicit none

! Define the variables
real(8) :: result_min, result_max ! Results for minimum and maximum values
real(8) :: min_point, max_point ! Points where minimum and maximum occur
real(8) :: left, right, tol ! Left and right bounds, and tolerance

interface
! Function with a minimum (example function - defined externally)
real(8) function f_min(x)
real(8), intent(in) :: x
end function f_min

! Function with a maximum (example function - defined externally)
real(8) function f_max(x)
real(8), intent(in) :: x
end function f_max
end interface

! The boundary values can vary depending on the problem context.
! In this example, they are chosen arbitrarily.
left = 0.0
right = 10.0

! The tolerance value defines how close the left and right bounds must be for the search to terminate.
tol = 1.0e-6

! Call the ternary search to find the minimum point of f_min
min_point = ternary_search_minimum(f_min, left, right, tol)
result_min = f_min(min_point)

! Call the ternary search to find the maximum point of f_max
max_point = ternary_search_maximum(f_max, left, right, tol)
result_max = f_max(max_point)

print *, "Minimum of the function f_min is at x =", min_point, "with value =", result_min
print *, "Maximum of the function f_max is at x =", max_point, "with value =", result_max

end program ternary_search_function_based

! Define the unimodal function f_min with a minimum near x = 5.0
! The quadratic term (x - 5.0)**2 defines a parabola that is concave upward with a minimum at x = 5.0
! and values increasing as x moves away from 5.
! The cosine term introduces oscillations, affecting the exact location of the minimum slightly away from 5.0.

real(8) function f_min(x)
real(8), intent(in) :: x
f_min = (x - 5.0)**2 + cos(x) ! Example of a quadratic function with a cosine oscillation
end function f_min

! Define the unimodal function f_max with a maximum near x = 5.0
! The quadratic term -(x - 5.0)**2 defines a parabola that is concave downward with a maximum at x = 5.0
! and values decreasing as x moves away from 5.
! The cosine term introduces oscillations, affecting the exact location of the maximum slightly away from 5.0.

real(8) function f_max(x)
real(8), intent(in) :: x
f_max = -(x - 5.0)**2 + cos(x) ! Example of a quadratic function with a cosine oscillation
end function f_max
152 changes: 152 additions & 0 deletions modules/searches/ternary_search_module.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
!> Ternary Search Algorithm Module
!!
!! This module implements two types of ternary search algorithms: array-based and function-based.
!! The array-based ternary search is used to find a target element within a sorted array, while the function-based
!! approach is used to find the minimum or maximum of a unimodal function.
!!
!! Array-based ternary search:
!! - Given a sorted array and a target, it splits the array into three parts and recursively searches for the target.
!!
!! Function-based ternary search:
!! - Used for unimodal functions, which have a single peak (maximum) or valley (minimum).
!! This method divides the function’s search space into thirds to converge on the minimum or maximum.
!!

module ternary_search
implicit none
contains

!> Array-based ternary search algorithm
!! This recursive function searches for the target value in a sorted array.
!!
!! Input:
!! - arr: The sorted array to search within.
!! - target: The value to search for.
!! - left, right: The range of indices within which to search.
!!
!! Output:
!! - The index of the target element if found, otherwise -1.
recursive integer function ternary_search_array(arr, target, left, right) result(result_index)
implicit none
integer, intent(in) :: arr(:) ! Array to search within
integer, intent(in) :: target ! Target value to search for
integer, intent(in) :: left, right ! Left and right indices
integer :: mid1, mid2 ! Midpoints
integer :: new_left, new_right ! Temporary indices

! Base case: if the range is invalid, return -1 (not found)
if (right < left) then
result_index = -1
return
end if

! Divide array into three parts
mid1 = left + (right - left)/3
mid2 = right - (right - left)/3

! Check if the target is at mid1 or mid2
if (arr(mid1) == target) then
result_index = mid1
return
else if (arr(mid2) == target) then
result_index = mid2
return
end if

! Recursive search in the appropriate third of the array
if (target < arr(mid1)) then
new_right = mid1 - 1
result_index = ternary_search_array(arr, target, left, new_right)
else if (target > arr(mid2)) then
new_left = mid2 + 1
result_index = ternary_search_array(arr, target, new_left, right)
else
new_left = mid1 + 1
new_right = mid2 - 1
result_index = ternary_search_array(arr, target, new_left, new_right)
end if
end function ternary_search_array

!> Function-based ternary search to find the minimum of a unimodal function
!! This function finds the minimum point of a unimodal function using the ternary search algorithm.
!!
!! Input:
!! - f: The unimodal function to search.
!! - left, right: The range within which to search for the minimum.
!! - tol: The tolerance to determine convergence.
!!
!! Output:
!! - The point at which the function achieves its minimum value.
recursive real(8) function ternary_search_minimum(f, left, right, tol) result(minimum)
implicit none
interface
real(8) function f(x)
real(8), intent(in) :: x
end function f
end interface
real(8), intent(in) :: left, right, tol
real(8) :: mid1, mid2
real(8) :: l, r

l = left
r = right

! Termination condition based on tolerance
do while (r - l > tol)
mid1 = l + (r - l)/3.0
mid2 = r - (r - l)/3.0

! Compare function values at midpoints
if (f(mid1) < f(mid2)) then
r = mid2
else
l = mid1
end if
end do

! The minimum point is approximately at the midpoint
minimum = (l + r)/2.0
end function ternary_search_minimum

!> Function-based ternary search to find the maximum of a unimodal function
!! This function finds the maximum point of a unimodal function using the ternary search algorithm.
!!
!! Input:
!! - f: The unimodal function to search.
!! - left, right: The range within which to search for the maximum.
!! - tol: The tolerance to determine convergence.
!!
!! Output:
!! - The point at which the function achieves its maximum value.
recursive real(8) function ternary_search_maximum(f, left, right, tol) result(maximum)
implicit none
interface
real(8) function f(x)
real(8), intent(in) :: x
end function f
end interface
real(8), intent(in) :: left, right, tol
real(8) :: mid1, mid2
real(8) :: l, r

l = left
r = right

! Termination condition based on tolerance
do while (r - l > tol)
mid1 = l + (r - l)/3.0
mid2 = r - (r - l)/3.0

! Compare function values at midpoints
if (f(mid1) > f(mid2)) then
r = mid2
else
l = mid1
end if
end do

! The maximum point is approximately at the midpoint
maximum = (l + r)/2.0
end function ternary_search_maximum

end module ternary_search