Open In App

Introduction to Invariants and Monovariants

Last Updated : 04 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Invariants and Monovariants are the two properties of mathematics and computer science that describe objects and algorithms. Invariants and mono variants are important mathematical concepts used to solve problems in mathematics, including algebra, geometry, etc.

  • We are able to enhance the efficiency of our solution and simplify problem-solving by identifying invariants and mono variants. 
  • This will also decrease the number of cases that are under consideration.

Invariants:

Invariant is a property where the value remains unchanged under certain operations and transformations. In other words, we can say that in invariant property a quantity remains constant or fixed throughout a process. In mathematical terms, we define invariant as a function whose value does not change under some operations and transformations.

Example: let’s have an example for a better understanding

Given an array and we have to find the maximum element in that array.

  • To solve this type of problem we can use an invariant to guarantee the highest element observed up to now is actually the largest element within the array.
  • We will declare a variable that is invariant in this case let that be ‘answer‘ is always the maximum element in that array till that index of the array. 
  • In starting we initialize it to be the first index of the array, and then check all the elements from there if the element is greater than the maximum element then we update that element and at last, we return the ‘answer‘ to get the maximum value.
  • Note that the invariant holds true at every step of the loop, and is never violated. This ensures that the algorithm is correct and will always find the maximum element in the array.

Below is the implementation  based on the above steps:

C++




// C++ code of the above approach
#include <iostream>
using namespace std;
 
// Declaring the solution function
// that return integer value.
int solution(int arr[], int n)
{
 
    // Initializing the answer variable
    // with first element of the array.
    int answer = arr[0];
 
    // Iterating through the whole array
    // and updating the answer variable.
    for (int i = 0; i < 6; i++) {
 
        // Checking that the answer
        // is smaller or not
        if (answer < arr[i]) {
 
            // Updating the value of
            // answer is smaller
            answer = arr[i];
        }
    }
 
    // Returning the answer that is
    // maximum element of whole array.
    return answer;
}
 
// Driver code;
int main()
{
 
    // Initializing the array
    int arr[6] = { 4, -2, 8, 6, 24, -28 };
 
    // Function call
    cout << solution(arr, 6);
    return 0;
}


Java




// Java code of the above approach
import java.util.*;
 
class Main {
    // Declaring the solution function
    // that return integer value.
    static int solution(int[] arr, int n)
    {
 
        // Initializing the answer variable
        // with first element of the array.
        int answer = arr[0];
 
        // Iterating through the whole array
        // and updating the answer variable.
        for (int i = 0; i < 6; i++) {
 
            // Checking that the answer
            // is smaller or not
            if (answer < arr[i]) {
 
                // Updating the value of
                // answer is smaller
                answer = arr[i];
            }
        }
 
        // Returning the answer that is
        // maximum element of whole array.
        return answer;
    }
 
    // Driver code;
    public static void main(String[] args)
    {
        // Initializing the array
        int[] arr = { 4, -2, 8, 6, 24, -28 };
 
        // Function call
        System.out.println(solution(arr, 6));
    }
}


Python3




# Python code of the above approach
 
# Declaring the solution function
# that return integer value.
 
 
def solution(arr, n):
 
    # Initializing the answer variable
    # with first element of the array.
    answer = arr[0]
 
    # Iterating through the whole array
    # and updating the answer variable.
    for i in range(6):
 
        # Checking that the answer
        # is smaller or not
        if answer < arr[i]:
 
            # Updating the value of
            # answer is smaller
            answer = arr[i]
 
    # Returning the answer that is
    # maximum element of whole array.
    return answer
 
 
# Driver code;
arr = [4, -2, 8, 6, 24, -28]
print(solution(arr, 6))


C#




// C# code of the above approach
using System;
 
public class GFG {
 
    // Declaring the solution function
    // that returns an integer value.
    public static int solution(int[] arr, int n)
    {
 
        // Initializing the answer variable
        // with first element of the array.
        int answer = arr[0];
 
        // Iterating through the whole array
        // and updating the answer variable.
        for (int i = 0; i < n; i++) {
 
            // Checking that the answer
            // is smaller or not
            if (answer < arr[i]) {
 
                // Updating the value of
                // answer is smaller
                answer = arr[i];
            }
        }
 
        // Returning the answer that is
        // maximum element of whole array.
        return answer;
    }
 
    // Driver code;
    public static void Main()
    {
 
        // Initializing the array
        int[] arr = { 4, -2, 8, 6, 24, -28 };
 
        // Function call
        Console.WriteLine(solution(arr, 6));
    }
}


Javascript




// Declaring the solution function
// that return integer value.
function solution(arr, n) {
 
    // Initializing the answer variable
    // with first element of the array.
    let answer = arr[0];
 
    // Iterating through the whole array
    // and updating the answer variable.
    for (let i = 0; i < 6; i++) {
 
        // Checking that the answer
        // is smaller or not
        if (answer < arr[i]) {
 
            // Updating the value of
            // answer is smaller
            answer = arr[i];
        }
    }
 
    // Returning the answer that is
    // maximum element of whole array.
    return answer;
}
 
// Driver code;
let arr = [4, -2, 8, 6, 24, -28];
 
// Function call
console.log(solution(arr, 6));


Output

24



Time complexity: O(n)
Auxiliary Space: O(1)

Monovariants:

Monovariants are invariant types that increase or decrease monotonically during transformations or operations. In other words, if an object is increasing continuously or decreasing continuously under certain transformations then we say that the object is a mono-variant. 

Example: Let’s have an example for better understanding:

Given a string of opening and closing brackets as a string. Find whether the string is balanced or not (It means every open bracket has a corresponding closed bracket or not).

  • We solve these types of problems using a monovariant. In order to solve this problem we define a variable ‘count‘ to track the count of opening and closing brackets expression. 
  • In this question, we define count as 0 and then we travel the whole string if we get opened bracket then we increase the count by 1 else we decrease the count by 1. 
  • If we get a negative count at any index then we break the loop and return “false“.
  • If our traversal is completed and the value of count is 0 then we return ‘True‘ else we return false.

Below is the implementation  based on the above steps:

C++




// C++ code of the above approach
#include <iostream>
using namespace std;
 
// Function that will return
// a boolean value.
bool solution(string s)
{
 
    // Initializing the value
    // of count to 0;
    int count = 0;
 
    // Traversing the whole string.
    for (int i = 0; i < s.length(); i++) {
 
        // Increasing the value of count
        // if we get '(' char at that index.
        if (s[i] == '(') {
            count++;
        }
 
        // Decreasing the value of the
        // count if we get ')' char
        // at that index.
        else {
            count--;
        }
 
        // Return false if a closed bracket
        // occur before the opening
        // bracket.
        if (count < 0) {
            return false;
        }
    }
 
    // Return true if the value
    // of the count is 0
    if (count == 0)
        return true;
 
    // If the count is not 0
    // then we return false.
    return false;
}
 
// Driver code
int main()
{
    string s1 = "(()()()(()))";
    string s2 = "(()()((()))";
 
    // Function call
    cout << solution(s1) << endl;
    cout << solution(s2) << endl;
 
    return 0;
}


Java




// Java code of the above approach
 
import java.io.*;
 
class GFG {
 
    // Function that will return a boolean value.
    static boolean solution(String s)
    {
 
        // Initializing the value of count to 0;
        int count = 0;
 
        // Traversing the whole string.
        for (int i = 0; i < s.length(); i++) {
            // Increasing the value of count if we get '('
            // char at that index.
            if (s.charAt(i) == '(') {
                count++;
            }
 
            // Decreasing the value of the count if we get
            // ')' char at that index.
            else {
                count--;
            }
 
            // Return false if a closed bracket occur before
            // the opening bracket.
            if (count < 0) {
                return false;
            }
        }
 
        // Return true if the value of the count is 0
        if (count == 0) {
            return true;
        }
 
        // If the count is not 0 then we return false.
        return false;
    }
 
    public static void main(String[] args)
    {
        String s1 = "(()()()(()))";
        String s2 = "(()()((()))";
 
        // Function call
        System.out.println(solution(s1) ? 1 : 0);
        System.out.println(solution(s2) ? 1 : 0);
    }
}
 
// This code is contributed by karthik.


Python3




# Function that will return
# a boolean value.
def solution(s):
       
    # Initializing the value
    # of count to 0;
    count = 0
     
     
    # Traversing the whole string.
    for i in range(len(s)):
          # Increasing the value of count
        # if we get '(' char at that index.
        if s[i] == '(':
            count += 1
        # Decreasing the value of the
        # count if we get ')' char
        # at that index.
        else:
            count -= 1
         
        # Return false if a closed bracket
        # occur before the opening
        # bracket.
        if count < 0:
            return 1
     
    # Return true if the value
    # of the count is 0
    if count == 0:
        return 1
     
    # If the count is not 0
    # then we return false
    return 0
 
   
# Driver code
s1 = "(()()()(()))"
s2 = "(()()((()))"
 
print(solution(s1))
print(solution(s2))


C#




using System;
 
// Function that will return
// a boolean value.
public class Solution {
    public static bool IsValid(string s) {
       
          // Initializing the value
        // of count to 0;
        int count = 0;
       
          // Traversing the whole string.
        for (int i = 0; i < s.Length; i++) {
               
              // Increasing the value of count
            // if we get '(' char at that index.
            if (s[i] == '(') {
                count++;
            }
           
              // Decreasing the value of the
                // count if we get ')' char
            // at that index.
            else {
                count--;
            }
           
              // Return false if a closed bracket
                // occur before the opening
            // bracket.
            if (count < 0) {
                return false;
            }
        }
           
          // Return result
        return count == 0;
    }
 
       
    // Driver code
    public static void Main(string[] args) {
        string s1 = "(()()()(()))";
        string s2 = "(()()((()))";
        Console.WriteLine(IsValid(s1));
        Console.WriteLine(IsValid(s2));
    }
}


Javascript




// JavaScript code of the above approach
 
// Function that will return
// a boolean value.
function solution(s) {
    // Initializing the value
    // of count to 0;
    let count = 0;
    // Traversing the whole string.
    for (let i = 0; i < s.length; i++) {
        // Increasing the value of count
        // if we get '(' char at that index.
        if (s[i] === '(') {
            count++;
        }
        // Decreasing the value of the
        // count if we get ')' char
        // at that index.
        else {
            count--;
        }
        // Return false if a closed bracket
        // occur before the opening
        // bracket.
        if (count < 0) {
            return false;
        }
    }
    // Return true if the value
    // of the count is 0
    if (count === 0)
        return true;
    // If the count is not 0
    // then we return false.
    return false;
}
// Driver code
let s1 = "(()()()(()))";
let s2 = "(()()((()))";
// Function call
console.log(solution(s1));
console.log(solution(s2));


Output

1
0

Difference between Invariant and Monovariant?

S.N

Invariant

Monovariant

1. A property or value that does not change its value throughout the number of processes or transformations. A function that changes its value in number of operations or transformations, but in a consistent way. (i.e. continuously increasing or decreasing manner).
2. This is used to prove that two figures or objects are similar and congruent or equivalent. This is used to analyze the change in value in the number of transformations by tracking.
3. Usually involves identifying a value or property that is preserved by certain operations. Usually involves identifying a value or property that consistently increases or decreases during a process.
4. Can be used to simplify complex problems by reducing them to a more manageable form. can be used to analyze complex systems by tracing changes over time or operations.
5. example:- Sum of angles of any figure is an invariant property. Example:- the area of a figure is a monovariant property.the 

Advantages of Invariants and monovariants:

  • They help us to reduce the complexity of the problem by reducing the number of variables to consider. 
  • They are particularly useful when the problem requires tracking a single variable over time such as the number of elements in a set or the number of inversions in an array.
  • They can be used to optimize the code by reducing the number of operations required to solve a problem.

Disadvantages of Invariants and monovariants:

  • Finding a suitable monovariant or variant can be challenging, particularly for complex problems.
  • They may not always exist for a problem.
  • They may not be unique, and there may be multiple monovariants or variants that can be used to solve a problem. 

Applications of Invariants and monovariants:

  • Monovariants are often used in mathematics problem-solving, particularly in algebra and geometry.
  • We often use invariants and monovariants in competitive programming to solve problems that involve sequences, sorting, searching, and traversal of graphs.
  • These are also used to find the correctness and efficiency of our algorithms in our solution.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads