Assignment of Practicum Session 10, Statistical Programming Parallel 2

Author

Arthur Zefanya Lauale (M0501261052)

(0). Library.

library(ggplot2)
library(knitr)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ lubridate 1.9.5     ✔ tibble    3.3.1
✔ purrr     1.2.2     ✔ tidyr     1.3.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

(A). Exercise 1.

Consider \(f(x) = x^3 - 2x - 5\).

  • Define the function and graph it over a suitable interval.

  • Find its real root using all four methods: Fixed-Point, Newton-Rhapson, Secant, and Bisection.

  • For Fixed-Point Iteration, construct an appropriate equivalent equation \(x = g(x)\).

  • For Newton-Raphson, write the first derivative manually.

  • Report each estimate, convergence status, and \(|f(\hat{x})|\).

  • Explain which method you found easiest to implement and why.

  • Optional: simulation of Newton Raphson and Bisection method.

(A). Answer Exercise (1).

  • Defining Function \(f(x) = x^3 - 2x - 5\) and Graphing It Using Suitable Interval.

    Here we define \(f(x) = x^3 - 2x - 5\) in R, to be graphed in suitable interval, so that we can know the location of the root.

# f_1
f_1 <- function(x) x^3 - 2*x - 5

# graph of f_1
curve(f_1,
      xlim = c(-2,4),
      ylim = c(-7,7),
      lwd = 2,
      col = "darkgreen",
      main = "Graph of f(x) = x^3 - 2x - 5",
      xlab = "x",
      ylab = "f(x)")
abline(h = 0,
       lty = 2,
       lwd = 1.5,
       col = "red")
legend("topleft",
       legend = "f(x)",
       col = "darkgreen",
       lty = 1,
       lwd = 2)

From the picture above we can know that the root of \(f(x)\) is close with \(2\), or we can say also root of \(f(x)\) is on range \([1.5, 2.5]\), so we can use \(2\) or \([1.5,2.5]\) to become initial value/range in estimating root of \(f(x)\).

  • Finding Root Using Fixed Point Method.

    • Defining Function fixedpoint.

      fixedpoint <- 
        function(F_1,
                 G_1,
                 initial_x_1,
                 desired_iter_1,
                 tol_1){
      
          # f_1
          f_1 <- function(x){
            eval(
              parse(
                text = F_1
              )
            )
          }
      
          # g_1
          g_1 <- function(x){
            eval(
              parse(
                text = G_1
              )
            )
          }
      
          # finding root, residu, and abs(f(root))
      
          x_1 <- c()
          x_1[1] <- initial_x_1
      
          residu_1 <- c()
          residu_1[1] <- 0
      
          abs_f_root_1 <- c()
          abs_f_root_1[1] <-
            abs(
              f_1(initial_x_1)
            )
      
          for(i in 1:(desired_iter_1 - 1)){
      
            # root
            x_1[i + 1] <- g_1(x_1[i])
      
            # residu
            residu_1[i + 1] <- x_1[i + 1] - x_1[i]
      
      
            # abs(f(root))
            abs_f_root_1[i + 1] <- 
              abs(
                f_1(x_1[i + 1])
              )
      
            # stopping criteria
            if(
              abs_f_root_1[i + 1] <= tol_1
            ) break
      
          }
      
          # x_1
          x_1
      
          # residu_1
          residu_1
      
          # abs_f_root_1
          abs_f_root_1
      
          # root_1
          root_1 <- x_1[
            length(x_1)
          ]
      
          # much_iter_1
          much_iter_1 <- i
      
          # saving result
          # result_1
          result_1 <- list(
            root = root_1, 
            root_complete = x_1,
            abs_f_root = abs_f_root_1,
            much_iter = much_iter_1,
            residu = residu_1
          )
      
          # showing_result
          return(result_1)
      
        }
    • Finding \(g(x)\).

      \[ \begin{flalign*} \begin{aligned} & f(x) = x^3 - 2x - 5 \\ & \\ & f(x) = 0 \\ & \iff x^3 - 2x - 5 = 0 \\ & \iff x^3 = 2x + 5 \\ & \iff x = (2x + 5)^{1/3} \\ \end{aligned} \end{flalign*} \]

      Take \((2x + 5)^{1/3}\) as \(g(x)\), so then we have \(g(x) = (2x + 5)^{1/3}\).

    • Finding Root of \(f(x)\).

      root_fixedpoint_1 <-
        fixedpoint(
          F_1 = "x^3 - 2*x - 5",
          G_1 = "(2*x + 5)^(1/3)",
          initial_x_1 = 2,
          desired_iter_1 = 10^3,
          tol_1 = 10^-6
        )
      root_fixedpoint_1$root
      [1] 2.094551
    • Trace of Root of \(f(x)\).

      # root_fixedpoint_1_table
      
      root_fixedpoint_1_table <-
        data.frame(
          iteration = 
            0:root_fixedpoint_1$much_iter,
          root = 
            root_fixedpoint_1$root_complete,
          residual = 
            root_fixedpoint_1$residu,
          abs_f_root =
            root_fixedpoint_1$abs_f_root
        )
      
      root_fixedpoint_1_table[
        rownames(root_fixedpoint_1_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_fixedpoint_1_table
      # into a kable format
      
      kable(
        root_fixedpoint_1_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Fixed Point Method"
      )
      Trace of Root of f(x) With Fixed Point Method
      iteration root residual abs_f_root
      0 2.000000 NA 1.0000000000
      1 2.080084 0.0800838231 0.1601676461
      2 2.092351 0.0122668547 0.0245337095
      3 2.094217 0.0018663182 0.0037326364
      4 2.094501 0.0002836562 0.0005673124
      5 2.094544 0.0000431053 0.0000862107
      6 2.094550 0.0000065503 0.0000131006
      7 2.094551 0.0000009954 0.0000019907
      8 2.094551 0.0000001513 0.0000003025
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(4\) the root value had been sticking in \(2.0945\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(2.094551\)). Based on that findings, we can define the convergence status of root which obtained by using Fixed Point method as like this.

      root_fixedpoint_1_conv_status <-
        TRUE
  • Finding Root Using Newton Raphson Method.

    • Defining Function newtonraphson.

      newtonraphson <- 
        function(F_2,
                 der_F_2,
                 initial_x_2,
                 desired_iter_2,
                 tol_2){
      
          # f_2
          f_2 <- function(x){
            eval(
              parse(
                text = F_2
              )
            )
          }
      
          # der_f_2
          der_f_2 <- function(x){
            eval(
              parse(
                text = der_F_2
              )
            )
          }
      
          # finding root, residu, and abs(f(root))
      
          x_2 <- c()
          x_2[1] <- initial_x_2
      
          residu_2 <- c()
          residu_2[1] <- 0
      
          abs_f_root_2 <- c()
          abs_f_root_2[1] <-
            abs(
              f_2(initial_x_2)
            )
      
          for(i in 1:(desired_iter_2 - 1)){
      
            # root
            x_2[i + 1] <- 
              x_2[i] - (f_2(x_2[i])/
                          der_f_2(x_2[i])
                        )
      
            # residu
            residu_2[i + 1] <- x_2[i + 1] - x_2[i]
      
            # abs(f(root))
            abs_f_root_2[i + 1] <- 
              abs(
                f_2(x_2[i + 1])
              )
      
            # stopping criteria
            if(
              abs_f_root_2[i + 1] <= tol_2
            ) break
      
          }
      
          # x_2
          x_2
      
          # residu_2
          residu_2
      
          # abs_f_root_2
          abs_f_root_2
      
          # root_2
          root_2 <- x_2[
            length(x_2)
          ]
      
          # much_iter_2
          much_iter_2 <- i
      
          # saving result
          # result_2
          result_2 <- list(
            root = root_2, 
            root_complete = x_2,
            abs_f_root = abs_f_root_2,
            much_iter = much_iter_2,
            residu = residu_2
          )
      
          # showing_result
          return(result_2)
      
        }
    • Finding \(f'(x)\).

      \[ \begin{flalign*} \begin{aligned} & f(x) = x^3 - 2x - 5 \\ & \\ & f'(x) = 3x^2 - 2\\ \end{aligned} \end{flalign*} \]

    • Finding Root of \(f(x)\).

      root_newtonraphson_1 <-
        newtonraphson(
          F_2 = "x^3 - 2*x - 5",
          der_F_2 = "3*x^2 - 2",
          initial_x_2 = 2,
          desired_iter_2 = 10^3,
          tol_2 = 10^-6
        )
      root_newtonraphson_1$root
      [1] 2.094551
    • Trace of Root of \(f(x)\).

      # root_newtonraphson_1_table
      
      root_newtonraphson_1_table <-
        data.frame(
          iteration = 
            0:root_newtonraphson_1$much_iter,
          root = 
            root_newtonraphson_1$root_complete,
          residual = 
            root_newtonraphson_1$residu,
          abs_f_root =
            root_newtonraphson_1$abs_f_root
        )
      
      root_newtonraphson_1_table[
        rownames(root_newtonraphson_1_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_newtonraphson_1_table
      # into a kable format
      
      kable(
        root_newtonraphson_1_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Newton Raphson Method"
      )
      Trace of Root of f(x) With Newton Raphson Method
      iteration root residual abs_f_root
      0 2.000000 NA 1.0000000000
      1 2.100000 0.1000000000 0.0610000000
      2 2.094568 -0.0054318789 0.0001857232
      3 2.094551 -0.0000166394 0.0000000017
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(2\) the root value had been sticking in \(2.0945\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(2.094551\)). Based on that findings, we can define the convergence status of root which obtained by using Newton Raphson method as like this.

      root_newtonraphson_1_conv_status <-
        TRUE
  • Finding Root Using Secant Method.

    • Defining Function secant.

      secant <- 
        function(F_3,
                 first_x_3,
                 second_x_3,
                 desired_iter_3,
                 tol_3){
      
          # f_3
          f_3 <- function(x){
            eval(
              parse(
                text = F_3
              )
            )
          }
      
          # finding root, residu, and abs(f(root))
      
          x_3 <- c()
          x_3[1] <- first_x_3
          x_3[2] <- second_x_3
      
          residu_3 <- c()
          residu_3[1] <- 0
          residu_3[2] <- x_3[2] - x_3[1]
      
          abs_f_root_3 <- c()
          abs_f_root_3[1] <-
            abs(
              f_3(x_3[1])
            )
          abs_f_root_3[2] <-
            abs(
              f_3(x_3[2])
            )
      
          for(i in 1:(desired_iter_3 - 2)){
      
            # root
            x_3[i + 2] <-
              x_3[i + 1] - (
                (f_3(x_3[i + 1]) * 
                   (x_3[i + 1] - x_3[i])
                   )/(
                     f_3(x_3[i + 1]) - f_3(x_3[i])
                   )
              )
      
            # residu
            residu_3[i + 2] <- x_3[i + 2] - x_3[i + 1]
      
            # abs(f(root))
            abs_f_root_3[i + 2] <- 
              abs(
                f_3(x_3[i + 2])
              )
      
            # stopping criteria
            if(
              abs_f_root_3[i + 2] <= tol_3
            ) break
      
          }
      
          # x_3
          x_3
      
          # residu_3
          residu_3
      
          # abs_f_root_3
          abs_f_root_3
      
          # root_3
          root_3 <- x_3[
            length(x_3)
          ]
      
          # much_iter_3
          much_iter_3 <- i
      
          # saving result
          # result_3
          result_3 <- list(
            root = root_3, 
            root_complete = x_3,
            abs_f_root = abs_f_root_3,
            much_iter = much_iter_3,
            residu = residu_3
          )
      
          # showing_result
          return(result_3)
      
        }
    • Finding Root of \(f(x)\).

      root_secant_1 <-
        secant(
          F_3 = "x^3 - 2*x - 5",
          first_x_3 = 1.5,
          second_x_3 = 2.5,
          desired_iter_3 = 10^3,
          tol_3 = 10^-6
        )
      root_secant_1$root
      [1] 2.094551
    • Trace of Root of \(f(x)\).

      # root_secant_1_table
      
      root_secant_1_table <-
        data.frame(
          iteration = 
            0:(root_secant_1$much_iter + 1),
          root = 
            root_secant_1$root_complete,
          residual = 
            root_secant_1$residu,
          abs_f_root =
            root_secant_1$abs_f_root
        )
      
      root_secant_1_table[
        rownames(root_secant_1_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_secant_1_table
      # into a kable format
      
      kable(
        root_secant_1_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Secant Method"
      )
      Trace of Root of f(x) With Secant Method
      iteration root residual abs_f_root
      0 1.500000 NA 4.6250000000
      1 2.500000 1.0000000000 5.6250000000
      2 1.951220 -0.5487804878 1.4736437370
      3 2.065144 0.1139241465 0.3228247858
      4 2.097101 0.0319577099 0.0285012776
      5 2.094509 -0.0025925647 0.0004763332
      6 2.094551 0.0000426165 0.0000006831
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(5\) the root value had been sticking in \(2.0945\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(2.094551\)). Based on that findings, we can define the convergence status of root which obtained by using Secant method as like this.

      root_secant_1_conv_status <-
        TRUE
  • Finding Root Using Bisection Method.

    • Defining Function bisection.

      bisection <- 
        function(F_4,
                 A_4,
                 B_4,
                 desired_iter_4,
                 tol_4){
      
          # f_4
          f_4 <- function(x){
            eval(
              parse(
                text = F_4
              )
            )
          }
      
          # finding root
          m_4 <- c()
          stopifnot(
            f_4(A_4)*f_4(B_4) < 0
          )
          for(i in 1 : desired_iter_4){
      
            # root
            m_4[i] <- (A_4 + B_4)/2
      
            # stopping criteria
            if(
              abs(
                f_4(m_4[i])
              ) <= tol_4 
            ) break
      
            # reverse variable
            if(
              f_4(A_4) * f_4(m_4[i]) <0
            ){
              B_4 <- m_4[i]
            } else {
              A_4 <- m_4[i]
            }
      
          }
      
          # m_4
          m_4
      
          # residu_4
          residu_4 <- c()
          residu_4[1] <- 0
          for(j in 1:
              (length(m_4) - 1)
          ){
            residu_4[j + 1] <- 
              m_4[j + 1] - m_4[j]
          }
      
          # abs_f_root_4
          abs_f_root_4 <- c()
          abs_f_root_4[1] <- 
            abs(f_4(
            m_4[1])
            )
          for(k in 1:
              (length(m_4) - 1)
          ){
            abs_f_root_4[k + 1] <-
              abs(f_4(
                m_4[k + 1]
                )
              )
          }
      
          # root_4
          root_4 <- m_4[
            length(m_4)
          ]
      
          # much_iter_4
          much_iter_4 <- i
      
          # saving result
          # result_4
          result_4 <- list(
            root = root_4, 
            root_complete = m_4,
            abs_f_root = abs_f_root_4,
            much_iter = much_iter_4,
            residu = residu_4
          )
      
          # showing_result
          return(result_4)
      
        }
    • Finding Root of \(f(x)\).

      root_bisection_1 <-
        bisection(
          F_4 = "x^3 - 2*x - 5",
          A_4 = 1.5,
          B_4 = 2.5,
          desired_iter_4 = 10^4,
          tol_4 = 10^-6
        )
      root_bisection_1$root
      [1] 2.094552
    • Trace of Root of \(f(x)\).

      # root_bisection_1_table
      
      root_bisection_1_table <-
        data.frame(
          iteration = 
            1:root_bisection_1$much_iter,
          root = 
            root_bisection_1$root_complete,
          residual = 
            root_bisection_1$residu,
          abs_f_root =
            root_bisection_1$abs_f_root
        )
      
      root_bisection_1_table[
        rownames(root_bisection_1_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_bisection_1_table
      # into a kable format
      
      kable(
        root_bisection_1_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Bisection Method"
      )
      Trace of Root of f(x) With Bisection Method
      iteration root residual abs_f_root
      1 2.000000 NA 1.0000000000
      2 2.250000 0.2500000000 1.8906250000
      3 2.125000 -0.1250000000 0.3457031250
      4 2.062500 -0.0625000000 0.3513183594
      5 2.093750 0.0312500000 0.0089416504
      6 2.109375 0.0156250000 0.1668357849
      7 2.101562 -0.0078125000 0.0785622597
      8 2.097656 -0.0039062500 0.0347142816
      9 2.095703 -0.0019531250 0.0128623322
      10 2.094727 -0.0009765625 0.0019543478
      11 2.094238 -0.0004882812 0.0034951492
      12 2.094482 0.0002441406 0.0007707752
      13 2.094604 0.0001220703 0.0005916927
      14 2.094543 -0.0000610352 0.0000895647
      15 2.094574 0.0000305176 0.0002510581
      16 2.094559 -0.0000152588 0.0000807453
      17 2.094551 -0.0000076294 0.0000044101
      18 2.094555 0.0000038147 0.0000381675
      19 2.094553 -0.0000019073 0.0000168787
      20 2.094552 -0.0000009537 0.0000062343
      21 2.094552 -0.0000004768 0.0000009121
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(14\) the root value had been sticking in \(2.0945\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(2.094552\)). Based on that findings, we can define the convergence status of root which obtained by using Bisection method as like this.

      root_bisection_1_conv_status <-
        TRUE
  • Report of Estimation, Convergence Status, and \(|f(\hat{x})|\).

# report_1
report_1 <- data.frame(
  method = c(
    "fixed point",
    "newton raphson",
    "secant",
    "bisection"
  ),
  estimation = c(
    root_fixedpoint_1$root,
    root_newtonraphson_1$root,
    root_secant_1$root,
    root_bisection_1$root
  ),
  convergent = c(
    root_fixedpoint_1_conv_status,
    root_newtonraphson_1_conv_status,
    root_secant_1_conv_status,
    root_bisection_1_conv_status
  ),
  abs_f_root = c(
    root_fixedpoint_1$abs_f_root[
      length(
        root_fixedpoint_1$abs_f_root
      )
    ],
    root_newtonraphson_1$abs_f_root[
      length(
        root_newtonraphson_1$abs_f_root
      )
    ],
    root_secant_1$abs_f_root[
      length(
        root_secant_1$abs_f_root
      )
    ],
    root_bisection_1$abs_f_root[
      length(
        root_bisection_1$abs_f_root
      )
    ]
  )
)

# showing report_1
kable(
  report_1,
  caption = "Report of Estimation, Convergence, and |f(x_hat)|"
)
Report of Estimation, Convergence, and |f(x_hat)|
method estimation convergent abs_f_root
fixed point 2.094552 TRUE 3e-07
newton raphson 2.094552 TRUE 0e+00
secant 2.094551 TRUE 7e-07
bisection 2.094552 TRUE 9e-07
  • Which Method Writer Found Easiest To Implement and Why.

    Disclaimer: this oppinion is subjective, maybe this opinion is not relate to other perople.

    For me when I will find the root of \(f(x)\) manually (without using computer), I prefer to choose Bisection method, because this method does not require advanced formula to be utilized/implemented/memorized. But it is not as the same as when I will look the root of \(f(x)\) helped by computer. For me, the algorithm of Bisection method is more complex than other methods, where algorithm of other methods (especially Fixed Point and Newton Raphson) do not need to reverse variables, yet Bisection method requires it, make me have to find residual and abs_f_root outside of looping which is used for finding the root (where in other methods I can simultantly find the residual and abs_f_root in the same looping used for finding the root). So when using computer without helped of any helper-function (only using basic language programming) I prefer to use Fixed Point or Newton Raphson Method.

  • Simulation of Newton Raphson Method.

    Disclaimer: this is not writer’s simulation - writer embedded this simulation from Geogebra site. True author of this simulation are: Κωνσταντίνος Ζυγούρης, TBennison, and Kathryn Peake.

  • Simulation of Bisection Method.

    Disclaimer: this is not writer’s simulation - writer embedded this simulation from Geogebra site. True author of this simulation is: Zuzana Moravkova.

(B). Exercise 2

Consdier \(f(x) = x^3 - x - 1\).

  • Draw the graph and identify an interval likely to contain a root.

  • Implement and compare four methods.

  • Try at least two different initial guesses for Newton-Raphson.

  • Explain why an unsuitable Fixed-Point rearrangement may fail even if the equation is algebraically equivalent.

(B). Answer Exercise 2.

  • Defining Function \(f(x) = x^3 - x - 1\) and Graphing It Using Suitable Interval.
# f_2
f_2 <- function(x) x^3 - x - 1

# graph of f_2
curve(f_2,
      xlim = c(-2,4),
      ylim = c(-7,7),
      lwd = 2,
      col = "darkgreen",
      main = "Graph of f(x) = x^3 - x - 1",
      xlab = "x",
      ylab = "f(x)")
abline(h = 0,
       lty = 2,
       lwd = 1.5,
       col = "red")
legend("topleft",
       legend = "f(x)",
       col = "darkgreen",
       lty = 1,
       lwd = 2)

From the picture above we can know that the root of \(f(x)\) is close with \(1\), or we can say also root of \(f(x)\) is on range \([1, 2]\), so we can use \(1\) or \([1,2]\) to become initial value/range in estimating root of \(f(x)\).

  • Finding Root Using Fixed Point Method.

    • Finding \(g(x)\).

      \[ \begin{flalign*} \begin{aligned} & f(x) = x^3 - x - 1 \\ & \\ & f(x) = 0 \\ & \iff x^3 - x - 1 = 0 \\ & \iff x^3 = x + 1 \\ & \iff x = (x + 1)^{1/3} \\ \end{aligned} \end{flalign*} \]

    • Finding Root of \(f(x)\).

      root_fixedpoint_2 <-
        fixedpoint(
          F_1 = "x^3 - x - 1",
          G_1 = "(x + 1)^(1/3)",
          initial_x_1 = 1,
          desired_iter_1 = 10^3,
          tol_1 = 10^-6
        )
      root_fixedpoint_2$root
      [1] 1.324718
    • Trace of Root of \(f(x)\).

      # root_fixedpoint_2_table
      
      root_fixedpoint_2_table <-
        data.frame(
          iteration = 
            0:root_fixedpoint_2$much_iter,
          root = 
            root_fixedpoint_2$root_complete,
          residual = 
            root_fixedpoint_2$residu,
          abs_f_root =
            root_fixedpoint_2$abs_f_root
        )
      
      root_fixedpoint_2_table[
        rownames(root_fixedpoint_2_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_fixedpoint_2_table
      # into a kable format
      
      kable(
        root_fixedpoint_2_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Fixed Point Method"
      )
      Trace of Root of f(x) With Fixed Point Method
      iteration root residual abs_f_root
      0 1.000000 NA 1.0000000000
      1 1.259921 0.2599210499 0.2599210499
      2 1.312294 0.0523727868 0.0523727868
      3 1.322354 0.0100599825 0.0100599825
      4 1.324269 0.0019149254 0.0019149254
      5 1.324633 0.0003638807 0.0003638807
      6 1.324702 0.0000691233 0.0000691233
      7 1.324715 0.0000131299 0.0000131299
      8 1.324717 0.0000024940 0.0000024940
      9 1.324718 0.0000004737 0.0000004737
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(6\) the root value had been sticking in \(1.3247\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(1.324718\)). Based on that findings, we can define the convergence status of root which obtained by using Fixed Point method as like this.

      root_fixedpoint_2_conv_status <-
        TRUE
  • Finding Root Using Newton Raphson Method With Initial Value \(x = 1\).

    • Finding \(f'(x)\).

      \[ \begin{flalign*} \begin{aligned} & f(x) = x^3 - x - 1\\ & \\ & f'(x) = 3x^2 - 1 \\ \end{aligned} \end{flalign*} \]

    • Finding Root of \(f(x)\).

      root_newtonraphson_2_a <-
        newtonraphson(
          F_2 = "x^3 - x - 1",
          der_F_2 = "3*x^2 - 1",
          initial_x_2 = 1,
          desired_iter_2 = 10^3,
          tol_2 = 10^-6
        )
      root_newtonraphson_2_a$root
      [1] 1.324718
    • Trace of Root of \(f(x)\).

      # root_newtonraphson_2_a_table
      
      root_newtonraphson_2_a_table <-
        data.frame(
          iteration = 
            0:root_newtonraphson_2_a$much_iter,
          root = 
            root_newtonraphson_2_a$root_complete,
          residual = 
            root_newtonraphson_2_a$residu,
          abs_f_root =
            root_newtonraphson_2_a$abs_f_root
        )
      
      root_newtonraphson_2_a_table[
        rownames(root_newtonraphson_2_a_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_newtonraphson_2_a_table
      # into a kable format
      
      kable(
        root_newtonraphson_2_a_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Newton Raphson Method"
      )
      Trace of Root of f(x) With Newton Raphson Method
      iteration root residual abs_f_root
      0 1.000000 NA 1.0000000000
      1 1.500000 0.500000000 0.8750000000
      2 1.347826 -0.152173913 0.1006821731
      3 1.325200 -0.022625688 0.0020583619
      4 1.324718 -0.000482225 0.0000009244
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(4\) the root value had been sticking in \(1.3247\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(1.324718\)). Based on that findings, we can define the convergence status of root which obtained by using Newton Raphson method (with initial value \(x = 1\)) as like this.

      root_newtonraphson_2_a_conv_status <-
        TRUE
  • Finding Root Using Newton Raphson Method With Initial Value \(x = 1.75\).

    • Finding Root of \(f(x)\).

      root_newtonraphson_2_b <-
        newtonraphson(
          F_2 = "x^3 - x - 1",
          der_F_2 = "3*x^2 - 1",
          initial_x_2 = 1.75,
          desired_iter_2 = 10^3,
          tol_2 = 10^-6
        )
      root_newtonraphson_2_b$root
      [1] 1.324718
    • Trace of Root of \(f(x)\).

      # root_newtonraphson_2_b_table
      
      root_newtonraphson_2_b_table <-
        data.frame(
          iteration = 
            0:root_newtonraphson_2_b$much_iter,
          root = 
            root_newtonraphson_2_b$root_complete,
          residual = 
            root_newtonraphson_2_b$residu,
          abs_f_root =
            root_newtonraphson_2_b$abs_f_root
        )
      
      root_newtonraphson_2_b_table[
        rownames(root_newtonraphson_2_b_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_newtonraphson_2_b_table
      # into a kable format
      
      kable(
        root_newtonraphson_2_b_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Newton Raphson Method"
      )
      Trace of Root of f(x) With Newton Raphson Method
      iteration root residual abs_f_root
      0 1.750000 NA 2.6093750000
      1 1.431298 -0.3187022901 0.5008775779
      2 1.333961 -0.0973364185 0.0397597662
      3 1.324797 -0.0091647034 0.0003353556
      4 1.324718 -0.0000786249 0.0000000246
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(3\) the root value had been sticking in \(1.3247\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(1.324718\)). Based on that findings, we can define the convergence status of root which obtained by using Newton Raphson method (with initial value \(x = 1.75\)) as like this.

      root_newtonraphson_2_b_conv_status <-
        TRUE
  • Finding Root Using Secant Method.

    • Finding Root of \(f(x)\).

      root_secant_2 <-
        secant(
          F_3 = "x^3 - x - 1",
          first_x_3 = 1,
          second_x_3 = 2,
          desired_iter_3 = 10^3,
          tol_3 = 10^-6
        )
      root_secant_2$root
      [1] 1.324718
    • Trace of Root of \(f(x)\).

      # root_secant_2_table
      
      root_secant_2_table <-
        data.frame(
          iteration = 
            0:(root_secant_2$much_iter + 1),
          root = 
            root_secant_2$root_complete,
          residual = 
            root_secant_2$residu,
          abs_f_root =
            root_secant_2$abs_f_root
        )
      
      root_secant_2_table[
        rownames(root_secant_2_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_secant_2_table
      # into a kable format
      
      kable(
        root_secant_2_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Secant Method"
      )
      Trace of Root of f(x) With Secant Method
      iteration root residual abs_f_root
      0 1.000000 NA 1.0000000000
      1 2.000000 1.0000000000 5.0000000000
      2 1.166667 -0.8333333333 0.5787037037
      3 1.253112 0.0864453665 0.2853630296
      4 1.337206 0.0840944126 0.0538805867
      5 1.323850 -0.0133563495 0.0036981154
      6 1.324708 0.0008578401 0.0000427343
      7 1.324718 0.0000100288 0.0000000346
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(6\) the root value had been sticking in \(1.3247\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(1.324718\)). Based on that findings, we can define the convergence status of root which obtained by using Secant method as like this.

      root_secant_2_conv_status <-
        TRUE
  • Finding Root Using Bisection Method.

    • Finding Root of \(f(x)\).

      root_bisection_2 <-
        bisection(
          F_4 = "x^3 - x - 1",
          A_4 = 1,
          B_4 = 2,
          desired_iter_4 = 10^4,
          tol_4 = 10^-6
        )
      root_bisection_2$root
      [1] 1.324718
    • Trace of Root of \(f(x)\).

      # root_bisection_2_table
      
      root_bisection_2_table <-
        data.frame(
          iteration = 
            1:root_bisection_2$much_iter,
          root = 
            root_bisection_2$root_complete,
          residual = 
            root_bisection_2$residu,
          abs_f_root =
            root_bisection_2$abs_f_root
        )
      
      root_bisection_2_table[
        rownames(root_bisection_2_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_bisection_2_table
      # into a kable format
      
      kable(
        root_bisection_2_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Bisection Method"
      )
      Trace of Root of f(x) With Bisection Method
      iteration root residual abs_f_root
      1 1.500000 NA 0.8750000000
      2 1.250000 -0.2500000000 0.2968750000
      3 1.375000 0.1250000000 0.2246093750
      4 1.312500 -0.0625000000 0.0515136719
      5 1.343750 0.0312500000 0.0826110840
      6 1.328125 -0.0156250000 0.0145759583
      7 1.320312 -0.0078125000 0.0187106133
      8 1.324219 0.0039062500 0.0021279454
      9 1.326172 0.0019531250 0.0062088296
      10 1.325195 -0.0009765625 0.0020366507
      11 1.324707 -0.0004882812 0.0000465949
      12 1.324951 0.0002441406 0.0009947910
      13 1.324829 -0.0001220703 0.0004740388
      14 1.324768 -0.0000610352 0.0002137072
      15 1.324738 -0.0000305176 0.0000835524
      16 1.324722 -0.0000152588 0.0000184779
      17 1.324715 -0.0000076294 0.0000140587
      18 1.324718 0.0000038147 0.0000022095
      19 1.324717 -0.0000019073 0.0000059246
      20 1.324718 0.0000009537 0.0000018576
      21 1.324718 0.0000004768 0.0000001760
    • Convergence Status of Estimated Root of \(f(x)\).

      Be noticed, since from iteration \(14\) the root value had been sticking in \(1.3247\) and on the same time abs_f_root value had been starting to approximate \(0\), then we can reveal that the estimated roots from each iteration are convergent to a specific value (that is \(1.324718\)). Based on that findings, we can define the convergence status of root which obtained by using Bisection method as like this.

      root_bisection_2_conv_status <-
        TRUE
  • Comparing Result From Four Methods.

# report_2
report_2 <- data.frame(
  method = c(
    "fixed point",
    "newt. raph. (in. val. = 1)",
    "newt. raph. (in. val. = 1.75)",
    "secant",
    "bisection"
  ),
  estimation = c(
    root_fixedpoint_2$root,
    root_newtonraphson_2_a$root,
    root_newtonraphson_2_b$root,
    root_secant_2$root,
    root_bisection_2$root
  ),
  iteration = c(
    root_fixedpoint_2$much_iter,
    root_newtonraphson_2_a$much_iter,
    root_newtonraphson_2_b$much_iter,
    root_secant_2$much_iter,
    root_bisection_2$much_iter
  ),
  convergent = c(
    root_fixedpoint_2_conv_status,
    root_newtonraphson_2_a_conv_status,
    root_newtonraphson_2_b_conv_status,
    root_secant_2_conv_status,
    root_bisection_2_conv_status
  ),
  abs_f_root = c(
    root_fixedpoint_2$abs_f_root[
      length(
        root_fixedpoint_2$abs_f_root
      )
    ],
    root_newtonraphson_2_a$abs_f_root[
      length(
        root_newtonraphson_2_a$abs_f_root
      )
    ],
    root_newtonraphson_2_b$abs_f_root[
      length(
        root_newtonraphson_2_b$abs_f_root
      )
    ],
    root_secant_2$abs_f_root[
      length(
        root_secant_2$abs_f_root
      )
    ],
    root_bisection_2$abs_f_root[
      length(
        root_bisection_2$abs_f_root
      )
    ]
  )
)

# showing report_2
kable(
  report_2,
  caption = "Comparison of Four Methods")
Comparison of Four Methods
method estimation iteration convergent abs_f_root
fixed point 1.324718 9 TRUE 5e-07
newt. raph. (in. val. = 1) 1.324718 4 TRUE 9e-07
newt. raph. (in. val. = 1.75) 1.324718 4 TRUE 0e+00
secant 1.324718 6 TRUE 0e+00
bisection 1.324718 21 TRUE 2e-07

From the table above we can know that from the estimation side, all methods produce the same root, that is \(\approx 1.324718\). From the iteration side, Bisection method do much more iterations than others, where it means that Bisection methods is more late in reaching the root, and Newton Rhapson method is faster in reaching the root. From the convergence side, all methods produce the result which are approximating a certain value. From the \(|f(\hat{x})|\) side, Newton Raphson (with initial value = \(1.75\)) and Secant method produce \(|f(\hat{x})|\) which are closest to \(0\), indicating that estimated roots as the result of these two methods are more precise. Therefore based on the simulation that we have done, we can conclude that for the precise result with low iteration time, we can consider to select Newton Rhapson method in finding root of \(f(x)\).

  • Explanation Why An Unsuitable Fixed-Point Rearrangement May Fail Even If The Equation Is Algebraically Equivalent.

From the given \(f(x) = x^3 - x - 1\) we can get another \(g(x) = x^3 - 1\). If we try to use this \(g(x)\) in function fixedpoint that we have made before, then we will find that the program will be error. One of the reasons why it happens is because the value of \(x_{i + 1} = g(x_i) = (x_{i + 1})^3 - 1\) which will decrease each time iteration increases. That power-three formulation makes \(g(x_{i})\) will always \(\leq 0\) even reach very little value (for the example \(-3.89017001 * 10^{8}\) at \(\pm \: 4th\) or \(5th\) iterations, with initial value \(=1\) ). It implies to the value of \(f(x = obtained \: root)\) which will be far from \(0\) as like as ilustrated below.

x_fixedpoint_2_b <- 
  c(0,-2,
    -9, -730,
    -3.89017001 * 10^-8)
f_x_fixedpoint_2_b <- 
  f_2(
    x_fixedpoint_2_b
  )
plot(
  x_fixedpoint_2_b,
  f_x_fixedpoint_2_b,
  col = "pink",
  type = "o",
  pch = 1,
  lwd = 2.5,
  xlab = "x",
  ylab = "f(x)"
)
legend(
  "topleft",
  legend = "f(x) = x^3 - x - 1",
  col = "pink",
  lty = 1,
  lwd = 2.5
)

Therefore we must be careful when choosing \(g(x)\), as much as possible for not choosing form \(g(x) = x^{b} ...\), but prefer to choose form \(g(x) = x^{-b}\) or \(g(x) = x^{\frac{1}{b}}\), that is choosing form that will produce value which is convergent to a certain value.

(C). Exercise 3.

Consider \(f(x) = 4x^2 - 3x - 7\).

  • Use Newton-Rhapson with \(x_0\) to find a root.

  • Repeat with a different starting value to search for another root.

  • Verify the results by substitution into the original function.

  • Compare the estimates with a suitable uniroot interval for each root.

(C). Answer Exercise 3.

  • Plot of Function \(f(x) = 4x^2 - 3x - 7\).
# f_3
f_3 <- function(x) 4*x^2 - 3*x - 7

# graph of f_3
curve(f_3,
      xlim = c(-2,4),
      ylim = c(-8,7),
      lwd = 2,
      col = "darkgreen",
      main = "Graph of f(x) = 4x^2 - 3x - 7",
      xlab = "x",
      ylab = "f(x)")
abline(h = 0,
       lty = 2,
       lwd = 1.5,
       col = "red")
legend("topleft",
       legend = "f(x)",
       col = "darkgreen",
       lty = 1,
       lwd = 2)

From the picture above we can know that the root of \(f(x)\) is close with \(-1\) and also close with \(2\), so we can use \(-1\) and also \(2\) to become initial value/range in estimating root of \(f(x)\). Other initial values actually is allowed to be used in finding root of \(f(x)\) as long as that initial value is not far from exact root.

  • Finding Root Using Newton Raphson Method With Initial Value \(x = 3\).

    • Finding \(f'(x)\).

      \[ \begin{flalign*} \begin{aligned} & f(x) = 4x^2 - 3x - 7\\ & \\ & f'(x) = 8x - 3 \\ \end{aligned} \end{flalign*} \]

    • Finding Root of \(f(x)\).

      root_newtonraphson_3_a <-
        newtonraphson(
          F_2 = "4*x^2 - 3*x - 7",
          der_F_2 = "8*x - 3",
          initial_x_2 = 3,
          desired_iter_2 = 10^3,
          tol_2 = 10^-6
        )
      root_newtonraphson_3_a$root
      [1] 1.75
    • Verifying The Estimated Root.

      # f_root_newtonraphson_3_a
      
      f_root_newtonraphson_3_a <-
        f_3(
          root_newtonraphson_3_a$root
        )
      
      f_root_newtonraphson_3_a
      [1] 2.502221e-07
    • Comparing The Estimated Root With Root Resulted by uniroot() Function.

      # uniroot_3_a
      
      uniroot_3_a <- 
        uniroot(f_3,
                interval= c(1,3),
                tol = 10^-6)$root
      
      uniroot_3_a
      [1] 1.75
      # f_uniroot_3_a
      
      f_uniroot_3_a <-
        f_3(
          uniroot_3_a
        )
      
      f_uniroot_3_a
      [1] -1.854773e-07
      # root_newtonraphson_3_a
      # vs
      # uniroot_3_a
      # compare_3_a
      
      compare_3_a <- data.frame(
        estimated = c(
          root_newtonraphson_3_a$root,
          f_root_newtonraphson_3_a
        ),
        uniroot = c(
          uniroot_3_a,
          f_uniroot_3_a
        )
      )
      rownames(compare_3_a) <- 
        c("root","f(root)")
      
      # showing comparison
      kable(
        x = compare_3_a,
        caption = 
          "Estimated Root vs Uniroot Root"
      )
      Estimated Root vs Uniroot Root
      estimated uniroot
      root 1.75e+00 1.75e+00
      f(root) 3.00e-07 -2.00e-07
  • Finding Root Using Newton Raphson Method With Initial Value \(x = -1\).

    • Finding Root of \(f(x)\).

      root_newtonraphson_3_b <-
        newtonraphson(
          F_2 = "4*x^2 - 3*x - 7",
          der_F_2 = "8*x - 3",
          initial_x_2 = -1,
          desired_iter_2 = 10^3,
          tol_2 = 10^-6
        )
      root_newtonraphson_3_b$root
      [1] -1
    • Verifying The Estimated Root.

      # f_root_newtonraphson_3_b
      
      f_root_newtonraphson_3_b <-
        f_3(
          root_newtonraphson_3_b$root
        )
      
      f_root_newtonraphson_3_b
      [1] 0
    • Comparing The Estimated Root With Root Resulted by uniroot() Function.

      # uniroot_3_b
      
      uniroot_3_b <- 
        uniroot(f_3,
                interval= c(-1,0),
                tol = 10^-6)$root
      
      uniroot_3_b
      [1] -1
      # f_uniroot_3_b
      
      f_uniroot_3_b <-
        f_3(
          uniroot_3_b
        )
      
      f_uniroot_3_b
      [1] 0
      # root_newtonraphson_3_b
      # vs
      # uniroot_3_b
      # compare_3_b
      
      compare_3_b <- data.frame(
        estimated = c(
          root_newtonraphson_3_b$root,
          f_root_newtonraphson_3_b
        ),
        uniroot = c(
          uniroot_3_b,
          f_uniroot_3_b
        )
      )
      rownames(compare_3_b) <- 
        c("root","f(root)")
      
      # showing comparison
      kable(
        x = compare_3_b,
        caption = 
          "Estimated Root vs Uniroot Root"
      )
      Estimated Root vs Uniroot Root
      estimated uniroot
      root -1 -1
      f(root) 0 0
  • Finding Root Using Newton Raphson Method With Initial Value \(x = 2\).

    • Finding Root of \(f(x)\).

      root_newtonraphson_3_c <-
        newtonraphson(
          F_2 = "4*x^2 - 3*x - 7",
          der_F_2 = "8*x - 3",
          initial_x_2 = 2,
          desired_iter_2 = 10^3,
          tol_2 = 10^-6
        )
      root_newtonraphson_3_c$root
      [1] 1.75
    • Verifying The Estimated Root.

      # f_root_newtonraphson_3_c
      
      f_root_newtonraphson_3_c <-
        f_3(
          root_newtonraphson_3_c$root
        )
      
      f_root_newtonraphson_3_c
      [1] 7.035183e-08
    • Comparing The Estimated Root With Root Resulted by uniroot() Function.

      # uniroot_3_c
      
      uniroot_3_c <- 
        uniroot(f_3,
                interval= c(1,2),
                tol = 10^-6)$root
      
      uniroot_3_c
      [1] 1.75
      # f_uniroot_3_c
      
      f_uniroot_3_c <-
        f_3(
          uniroot_3_c
        )
      
      f_uniroot_3_c
      [1] -1.039177e-06
      # root_newtonraphson_3_c
      # vs
      # uniroot_3_c
      # compare_3_c
      
      compare_3_c <- data.frame(
        estimated = c(
          root_newtonraphson_3_c$root,
          f_root_newtonraphson_3_c
        ),
        uniroot = c(
          uniroot_3_c,
          f_uniroot_3_c
        )
      )
      rownames(compare_3_c) <- 
        c("root","f(root)")
      
      # showing comparison
      kable(
        x = compare_3_c,
        caption = 
          "Estimated Root vs Uniroot Root"
      )
      Estimated Root vs Uniroot Root
      estimated uniroot
      root 1.75e+00 1.750000
      f(root) 1.00e-07 -0.000001

(D). Exercise 4.

For the equation \(log(x) - e^{-x} = 0\), compare

     \(g_1(x) = e^{e^{-x}}\) and \(g_2(x) = x + log(x) - e^{-x}\)

  • Start both iterations from \(x_0 = 2\), with tol \(= 1e-6\) and max.iter \(= 20\).

  • Plot the iteration values against the iteration number.

  • State which iterations converges and which does not.

  • Explain the difference in behavior in your own words.

(D). Answer Exercise 4.

  • Plot of Function \(f(x) = log(x) - e^{-x}\).
# f_4
f_4 <- function(x) log(x) - exp(-x)

# graph of f_4
curve(f_4,
      xlim = c(0.1,4),
      ylim = c(-5,7),
      lwd = 2,
      col = "darkgreen",
      main = "Graph of f(x) = log(x) - e^(-x)",
      xlab = "x",
      ylab = "f(x)")
abline(h = 0,
       lty = 2,
       lwd = 1.5,
       col = "red")
legend("topleft",
       legend = "f(x)",
       col = "darkgreen",
       lty = 1,
       lwd = 2)

  • Finding Root Using Fixed Point Method With \(g_{1}(x) = e^{e^{-x}}\).

    • Finding Root of \(f(x)\).

      root_fixedpoint_4_a <-
        fixedpoint(
          F_1 = "log(x) - exp(-x)",
          G_1 = "exp(exp(-x))",
          initial_x_1 = 2,
          desired_iter_1 = 20 + 1,
          tol_1 = 10^-6
        )
      root_fixedpoint_4_a$root
      [1] 1.309799
    • Trace of Root of \(f(x)\).

      # root_fixedpoint_4_a_table
      
      root_fixedpoint_4_a_table <-
        data.frame(
          iteration = 
            0:root_fixedpoint_4_a$much_iter,
          root = 
            root_fixedpoint_4_a$root_complete,
          residual = 
            root_fixedpoint_4_a$residu,
          abs_f_root =
            root_fixedpoint_4_a$abs_f_root
        )
      
      root_fixedpoint_4_a_table[
        rownames(root_fixedpoint_4_a_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_fixedpoint_4_a_table
      # into a kable format
      
      kable(
        root_fixedpoint_4_a_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Fixed Point Method"
      )
      Trace of Root of f(x) With Fixed Point Method
      iteration root residual abs_f_root
      0 2.000000 NA 0.5578118973
      1 1.144921 -0.8550794073 0.1829139049
      2 1.374719 0.2297981894 0.0653384793
      3 1.287768 -0.0869504968 0.0229750861
      4 1.317697 0.0299290824 0.0081346699
      5 1.307022 -0.0106755532 0.0028737033
      6 1.310783 0.0037613948 0.0010160148
      7 1.309452 -0.0013310988 0.0003591149
      8 1.309922 0.0004703283 0.0001269437
      9 1.309756 -0.0001662758 0.0000448718
      10 1.309815 0.0000587724 0.0000158614
      11 1.309794 -0.0000207753 0.0000056067
      12 1.309802 0.0000073436 0.0000019819
      13 1.309799 -0.0000025958 0.0000007005
  • Finding Root Using Fixed Point Method With \(g_{2}(x) = x + log(x) - e^{-x}\).

    • Finding Root of \(f(x)\).

      root_fixedpoint_4_b <-
        fixedpoint(
          F_1 = "log(x) - exp(-x)",
          G_1 = "x + log(x) - exp(-x)",
          initial_x_1 = 2,
          desired_iter_1 = 20 + 1,
          tol_1 = 10^-6
        )
      root_fixedpoint_4_b$root
      [1] 55.64637
    • Trace of Root of \(f(x)\).

      # root_fixedpoint_4_b_table
      
      root_fixedpoint_4_b_table <-
        data.frame(
          iteration = 
            0:root_fixedpoint_4_b$much_iter,
          root = 
            root_fixedpoint_4_b$root_complete,
          residual = 
            root_fixedpoint_4_b$residu,
          abs_f_root =
            root_fixedpoint_4_b$abs_f_root
        )
      
      root_fixedpoint_4_b_table[
        rownames(root_fixedpoint_4_b_table) == "1",
        "residual"
      ] <- NA
      
      # insert root_fixedpoint_4_b_table
      # into a kable format
      
      kable(
        root_fixedpoint_4_b_table,
        digits = 10,
        caption = "Trace of Root of f(x) 
        With Fixed Point Method"
      )
      Trace of Root of f(x) With Fixed Point Method
      iteration root residual abs_f_root
      0 2.000000 NA 0.5578119
      1 2.557812 0.5578119 0.8616781
      2 3.419490 0.8616781 1.1967623
      3 4.616252 1.1967623 1.5196934
      4 6.135946 1.5196934 1.8120005
      5 7.947946 1.8120005 2.0725602
      6 10.020506 2.0725602 2.3045892
      7 12.325096 2.3045892 2.5116330
      8 14.836729 2.5116330 2.6971054
      9 17.533834 2.6971054 2.8641324
      10 20.397966 2.8641324 3.0154352
      11 23.413402 3.0154352 3.1533086
      12 26.566710 3.1533086 3.2796589
      13 29.846369 3.2796589 3.3960632
      14 33.242432 3.3960632 3.5038271
      15 36.746259 3.5038271 3.6040364
      16 40.350296 3.6040364 3.6975987
      17 44.047895 3.6975987 3.7852776
      18 47.833172 3.7852776 3.8677194
      19 51.700891 3.8677194 3.9454750
      20 55.646366 3.9454750 4.0190168
  • Plot of Iteration Number vs Obtained Root.

plot(
  0:root_fixedpoint_4_a$much_iter,
  root_fixedpoint_4_a$root_complete,
  type = "o",
  col = "blue",
  pch = 1,
  lty = 1,
  lwd = 2,
  main = "Trend of Obtained Root Against Iteration Number",
  xlab = "iteration",
  ylab = "root",
  xlim = c(0,22),
  ylim = c(1,60))
lines(
  0:root_fixedpoint_4_b$much_iter,
  root_fixedpoint_4_b$root_complete,
  type = "o",
  col = "gold",
  pch = 1,
  lty = 1,
  lwd = 2
)
legend(
  "topleft",
  legend = 
    c(
      "using g1(x) = exp(exp(-x))",
      "using g2(x) = x + log(x) - exp(-x)"
    ),
  col = c("blue",
          "gold"),
  lty = c(1,1),
  lwd = c(2,2)
)
grid()

From the visualization above we can see that curve of iterations using \(g_1(x) = e^{e^{-x}}\) seems to descend and curve of iterations using \(g_2(x) = x + log(x) - e^{-x}\) seemes to ascend. It means that by using \(g_1(x) = e^{e^{-x}}\) we will obtain a certain value as the root of \(f(x)\), meanwhile by using \(g_2(x) = x + log(x) - e^{-x}\) we won’t obtain a (fixed) certain value (a.k.a we won’t obtain the root).

The reason why by using \(g_1(x)\) we can obtain root meanwhile by using \(g_2(x)\) we won’t reach the root is back to the nature of each function.

If we use \(g_1(x) = e^{e^{-x}}\) then when we substitute with a certain \(x\), let ’s say we take \(x = -1\), then we will obtain \(g_1(-1) \approx 15.15426\), and we take that \(15.15426\) to be \(x\), then we will obtain \(g_1(15.15426) \approx 1\), and so on until we will find a certain \(x\) with value \(\approx 1.3098\), where \(f(1.3098) \approx 0\).

It is different if we use \(g_2(x) = x + log(x) - e^{-x}\), it means domain for this function must be \(x > 0\), so it means that part \(x \: + \: log(x)\) must always be positive, and part \(e^{-x}\) will approximate to \(0\) as the number of iterations increases. It means that \(g_2(x)\) does not approximate to a (fixed) certain value which also means we won’t obtain the root of \(f(x)\).

(E). Exercise 5

Modify the bisection() function so that it:

  • Prints a clear message if the starting interval does not bracket a root.

  • Returns a table containing the midpoint and resiudal \(|f(x_m)|\) at every iteration.

  • Stops using both an interval-width criterion and a function-residual critertion.

  • Is tested on \(x^3 - 2x - 5 = 0\).

(E). Answer Exercise 5

  • Function bisection_new.
bisection_new <- 
  function(F_5,
           A_5,
           B_5,
           desired_iter_5,
           tol_5){
    
    # f_5
    f_5 <- function(x){
      eval(
        parse(
          text = F_5
        )
      )
    }
    
    # interval contains/
    # not contain root
    if(
      f_5(A_5)*f_5(B_5) > 0 
    ){
      stop("Submitted interval does not contain root.")
    }
    
    # finding root
    m_5 <- c()
    for(i in 1 : desired_iter_5){
      
      # root
      m_5[i] <- (A_5 + B_5)/2
      
      # stopping criteria
      if(
        abs(
          f_5(m_5[i])
        ) <= tol_5 
      ) break
      
      # reverse variable
      if(
        f_5(A_5) * f_5(m_5[i]) <0
      ){
        B_5 <- m_5[i]
      } else {
        A_5 <- m_5[i]
      }
      
    }
    
    # m_5
    m_5
    
    # residu_5
    residu_5 <- c()
    residu_5[1] <- 0
    for(j in 1:
        (length(m_5) - 1)
    ){
      residu_5[j + 1] <- 
        m_5[j + 1] - m_5[j]
    }
    
    # abs_f_root_5
    abs_f_root_5 <- c()
    abs_f_root_5[1] <- 
      abs(f_5(
        m_5[1])
      )
    for(k in 1:
        (length(m_5) - 1)
    ){
      abs_f_root_5[k + 1] <-
        abs(f_5(
          m_5[k + 1]
        )
        )
    }
    
    # root_5
    root_5 <- m_5[
      length(m_5)
    ]
    
    # much_iter_5
    much_iter_5 <- i
    
    # residual_abs_f_root_5
    residu_abs_f_root_5 <- c()
    residu_abs_f_root_5[1] <- 0
    for(l in 1:
        (length(m_5) - 1)){
      residu_abs_f_root_5[l + 1] <-
        abs_f_root_5[l + 1] -
        abs_f_root_5[l]
    }
    
    # table_result_5
    table_result_5 <- 
      data.frame(
        iteration = 1:much_iter_5,
        root = m_5,
        abs_f_root = 
          abs_f_root_5,
        residu_abs_f_root = 
          residu_abs_f_root_5
      )
    
    table_result_5[
      1,4
    ] <- NA
      
    # saving result
    # result_5
    result_5 <- list(
      root = root_5, 
      root_complete = m_5,
      abs_f_root = abs_f_root_5,
      much_iter = much_iter_5,
      residu = residu_5,
      table_result = kable(
        table_result_5,
        caption = "Result of Bisection")
    )
    
    # showing_result
    return(result_5)
    
  }
  • Using bisection_new To Find The Solution of \(f(x) = x^3 - 2x - 5\).
# position of root of f(x)
f_5 <- function(x){
  x^3 - 2*x - 5
}
curve(f_5,
      xlim = c(-2,3),
      col = "darkgreen",
      xlab = "x",
      ylab = "f(x)",
      lwd = 2.5,
      main = "curve of f(x) = x^3 - 2x - 5")
abline(h = 0,
       lty = 2,
       lwd = 1.5,
       col = "blue")
legend(
  "topleft",
  legend = "f(x)",
  col = "darkgreen",
  lty = 1,
  lwd = 2.5
)

# root_bisection_5
root_bisection_5 <- 
  bisection_new(
    "x^3 - 2*x - 5",
    1.5,
    2.5,
    10^3,
    10^-6
  )

root_bisection_5
$root
[1] 2.094552

$root_complete
 [1] 2.000000 2.250000 2.125000 2.062500 2.093750 2.109375 2.101562 2.097656
 [9] 2.095703 2.094727 2.094238 2.094482 2.094604 2.094543 2.094574 2.094559
[17] 2.094551 2.094555 2.094553 2.094552 2.094552

$abs_f_root
 [1] 1.000000e+00 1.890625e+00 3.457031e-01 3.513184e-01 8.941650e-03
 [6] 1.668358e-01 7.856226e-02 3.471428e-02 1.286233e-02 1.954348e-03
[11] 3.495149e-03 7.707752e-04 5.916927e-04 8.956468e-05 2.510581e-04
[16] 8.074527e-05 4.410068e-06 3.816751e-05 1.687870e-05 6.234310e-06
[21] 9.121196e-07

$much_iter
[1] 21

$residu
 [1]  0.000000e+00  2.500000e-01 -1.250000e-01 -6.250000e-02  3.125000e-02
 [6]  1.562500e-02 -7.812500e-03 -3.906250e-03 -1.953125e-03 -9.765625e-04
[11] -4.882812e-04  2.441406e-04  1.220703e-04 -6.103516e-05  3.051758e-05
[16] -1.525879e-05 -7.629395e-06  3.814697e-06 -1.907349e-06 -9.536743e-07
[21] -4.768372e-07

$table_result


Table: Result of Bisection

| iteration|     root| abs_f_root| residu_abs_f_root|
|---------:|--------:|----------:|-----------------:|
|         1| 2.000000|  1.0000000|                NA|
|         2| 2.250000|  1.8906250|         0.8906250|
|         3| 2.125000|  0.3457031|        -1.5449219|
|         4| 2.062500|  0.3513184|         0.0056152|
|         5| 2.093750|  0.0089417|        -0.3423767|
|         6| 2.109375|  0.1668358|         0.1578941|
|         7| 2.101562|  0.0785623|        -0.0882735|
|         8| 2.097656|  0.0347143|        -0.0438480|
|         9| 2.095703|  0.0128623|        -0.0218519|
|        10| 2.094727|  0.0019543|        -0.0109080|
|        11| 2.094238|  0.0034951|         0.0015408|
|        12| 2.094482|  0.0007708|        -0.0027244|
|        13| 2.094604|  0.0005917|        -0.0001791|
|        14| 2.094543|  0.0000896|        -0.0005021|
|        15| 2.094574|  0.0002511|         0.0001615|
|        16| 2.094559|  0.0000807|        -0.0001703|
|        17| 2.094551|  0.0000044|        -0.0000763|
|        18| 2.094555|  0.0000382|         0.0000338|
|        19| 2.094553|  0.0000169|        -0.0000213|
|        20| 2.094552|  0.0000062|        -0.0000106|
|        21| 2.094552|  0.0000009|        -0.0000053|