ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Discrete Structures
    CSI-303
    Progress0 / 21 topics
    Topics
    1. Introduction to Logic and Proofs2. Direct Proofs3. Proof by Contradiction4. Sets5. Combinatorics6. Sequences7. Formal Logic8. Propositional and Predicate Calculus9. Methods of Proof10. Mathematical Induction and Recursion11. Loop Invariants12. Relations and Functions13. Pigeonhole Principle14. Trees and Graphs15. Elementary Number Theory16. Optimization and Matching17. Fundamental Structures18. Functions19. Relations (Recursions)20. Cardinality and Countability21. Probabilistic Methods
    CSI-303›Loop Invariants
    Discrete StructuresTopic 11 of 21

    Loop Invariants

    6 minread
    1,053words
    Intermediatelevel

    Loop Invariants

    A loop invariant is a property or condition that holds true before and after each iteration of a loop. These invariants are useful for proving the correctness of algorithms, particularly when trying to show that a loop correctly solves a problem or that an algorithm terminates as expected.

    Key Concepts of Loop Invariants

    A loop invariant is a statement or condition that:

    1. Holds true before the first iteration of the loop.
    2. Remains true after each iteration of the loop, i.e., it is preserved as the loop executes.
    3. Helps in proving correctness: The invariant is usually tied to the correctness of the algorithm, allowing you to prove that the loop eventually produces the correct result once it terminates.

    Structure of a Loop Invariant

    To effectively use a loop invariant in a proof, you must identify:

    1. Initialization: Prove that the invariant is true before the loop starts (usually at the beginning of the first iteration).
    2. Maintenance: Show that if the invariant is true before an iteration of the loop, it remains true after that iteration.
    3. Termination: After the loop terminates, use the invariant to help prove that the algorithm has the desired outcome.

    Example of Loop Invariant: Finding the Maximum Element in an Array

    Let's look at an example where we use a loop invariant to prove that a loop correctly finds the maximum element in an array.

    Problem: Find the maximum element in an array.

    We are given an array AAA of length nnn, and we want to find the maximum element in this array. We can write a simple loop to do this:

    max_element = A[0]
    for i in range(1, n):
        if A[i] > max_element:
            max_element = A[i]
    

    Identifying the Loop Invariant

    We define the loop invariant for this algorithm:

    • Invariant: At the start of each iteration of the loop (at index iii), max_element contains the maximum value of the array elements from A[0] to A[i-1].

    Now, let's prove that this invariant holds.

    1. Initialization: Before the loop starts, max_element = A[0], so the invariant holds because the maximum value from A[0] to A[-1] (an empty set) is trivially valid.

    2. Maintenance: Assume that the invariant holds at the start of some iteration iii. That is, max_element contains the maximum value in the subarray A[0] to A[i-1]. In the iii-th iteration, we compare A[i] with max_element. If A[i] > max_element, we update max_element to be A[i]. After this step, max_element will still hold the maximum value in the subarray A[0] to A[i]. Hence, the invariant is maintained.

    3. Termination: When the loop terminates, the index iii will be equal to nnn, meaning the loop has considered all elements in the array. By the invariant, max_element will contain the maximum value from A[0] to A[n-1], which is the maximum element of the entire array.

    Thus, the loop correctly finds the maximum element in the array.


    Another Example: Sorting (Selection Sort)

    Let’s look at another example, this time using a loop invariant in the selection sort algorithm. The idea behind selection sort is to repeatedly find the minimum element from the unsorted part of the list and swap it with the first unsorted element.

    Selection Sort Algorithm:

    for i in range(n-1):
        min_index = i
        for j in range(i+1, n):
            if A[j] < A[min_index]:
                min_index = j
        A[i], A[min_index] = A[min_index], A[i]
    

    Loop Invariant for Selection Sort

    We define the loop invariant for this algorithm:

    • Invariant: At the start of each iteration of the outer loop (at index iii), the subarray A[0] to A[i-1] is sorted, and each element in this subarray is smaller than every element in the unsorted subarray A[i] to A[n-1].

    Let’s prove that this invariant holds.

    1. Initialization: Before the first iteration, the subarray A[0] to A[-1] is empty, so the invariant trivially holds because an empty subarray is considered sorted.

    2. Maintenance: Assume that the invariant holds at the start of some iteration iii, meaning the subarray A[0] to A[i-1] is sorted, and each element in it is smaller than every element in the subarray A[i] to A[n-1]. In the iii-th iteration, the inner loop finds the minimum element in the unsorted subarray A[i] to A[n-1]. We then swap this minimum element with A[i], ensuring that the element A[i] is now in its correct sorted position. The rest of the subarray remains sorted, and the elements before A[i] are still smaller than those after. Therefore, the invariant is maintained.

    3. Termination: When the outer loop terminates, the index iii will be equal to n−1n-1n−1, meaning that the entire array is sorted. By the invariant, the subarray A[0] to A[n-1] is sorted, and all the elements in it are smaller than the unsorted part (which is empty). Hence, the entire array is sorted.

    Thus, the selection sort algorithm correctly sorts the array.


    Using Loop Invariants in Algorithm Analysis

    Loop invariants can be used not only for proving correctness but also for analyzing the performance of algorithms. By proving an invariant, we can often infer properties like:

    • Time complexity: How many iterations the loop will run.
    • Space complexity: The space needed by the algorithm, especially in recursive algorithms.
    • Termination: When and why a loop will terminate.

    For example, the invariant in selection sort helps us show that after n−1n-1n−1 iterations, the array is sorted, and each iteration involves finding the minimum element from an unsorted subarray, confirming the algorithm’s correctness and efficiency.


    Conclusion

    Loop invariants are a powerful tool in algorithm design and analysis. They provide a way to reason about the behavior of loops in algorithms, ensuring that the algorithm produces the correct output. By proving that a loop invariant holds at the start, after each iteration, and at the end, we can demonstrate the correctness of algorithms, especially for sorting, searching, and other iterative processes. Understanding and using loop invariants is a crucial skill for analyzing and proving the behavior of algorithms.

    Previous topic 10
    Mathematical Induction and Recursion
    Next topic 12
    Relations and Functions

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time6 min
      Word count1,053
      Code examples0
      DifficultyIntermediate