Skip to content

Commit

Permalink
Merge branch 'main' into feature/numerical_integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramy-Badr-Ahmed authored Sep 29, 2024
2 parents e281889 + 49fffac commit e45a412
Show file tree
Hide file tree
Showing 7 changed files with 306 additions and 2 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/check_code_format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: check_code_format

'on':
workflow_dispatch:
push:
branches:
- main
pull_request:

jobs:
check_format_code:
name: check format code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install fprettify
run: pip install fprettify

- name: Display fprettify version
run: fprettify --version

- name: Format code
run: |
git clean -f -x -d
fprettify --indent 4 --recursive .
- name: Fail if needs reformatting
run: |
if [[ $(git status --porcelain) ]]; then
echo "please reformat/fprettify these files:"
git status --porcelain=v1
exit 1
fi
- name: Exact diff of needed reformatting
if: failure()
run: git diff
...
11 changes: 10 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
cmake_minimum_required(VERSION 3.16)
project(FortranProject LANGUAGES Fortran)

add_compile_options(-Wall -Wextra -Wpedantic)
add_compile_options(
-Wall
-Wextra
-Wpedantic
-Waliasing
-Wconversion-extra
-Wimplicit-interface
-Wimplicit-procedure
-Wsurprising
-Werror)

function(add_fortran_sources DIR SOURCES)
file(GLOB_RECURSE NEW_SOURCES "${DIR}/*.f90")
Expand Down
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<!-- Second row: -->
<br>
<a href="https://github.com/TheAlgorithms/Fortran/actions">
<img src="https://img.shields.io/github/actions/workflow/status/TheAlgorithms/Fortran/build.yml?branch=master&label=CI&logo=github&style=flat-square" height="20" alt="GitHub Workflow Status">
<img src="https://img.shields.io/github/actions/workflow/status/TheAlgorithms/Fortran/ci.yml?branch=main&label=CI&logo=github&style=flat-square" height="20" alt="GitHub Workflow Status">
</a>
<a href="https://github.com/pre-commit/pre-commit">
<img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" height="20" alt="pre-commit">
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
74 changes: 74 additions & 0 deletions examples/searches/example_ternary_search_function_based.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
!> Example Program: Function-based Ternary Search for Minimum and Maximum
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #24
!! https://github.com/TheAlgorithms/Fortran/pull/24
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! 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
integer, parameter :: dp = kind(0.0d0) ! Define double precision kind
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.0d0
right = 10.0d0

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

! 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.0d0)**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.0d0)**2 + cos(x) ! Example of a quadratic function with a cosine oscillation
end function f_max
160 changes: 160 additions & 0 deletions modules/searches/ternary_search_module.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
!> Ternary Search Algorithm Module
!!
!! This module implements two types of ternary search algorithm: array-based and function-based.
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #24
!! https://github.com/TheAlgorithms/Fortran/pull/24
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! 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.0d0
mid2 = r - (r - l)/3.0d0

! 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.0d0
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.0d0
mid2 = r - (r - l)/3.0d0

! 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.0d0
end function ternary_search_maximum

end module ternary_search

0 comments on commit e45a412

Please sign in to comment.