## 2 Materials and Methods
### Genetic Programming Based Symbolic Regression  
The dataset is modeled using a mathematical expression to gain deeper insights into the SNR values generated and predict future SNR values using the mathematical expression. To find a mathematical expression that best fits a given dataset, Symbolic Regression is applied to the dataset. It is a type of regression analysis in which the goal is to find a mathematical expression that best fits a given set of data points. In contrast to traditional regression methods that use predefined functions such as linear or polynomial equations, Symbolic Regression allows the model to discover its own functional form by searching through a space of mathematical expressions. Genetic programming is a type of evolutionary algorithm that is used to find solutions to complex problems by mimicking the process of natural selection. In genetic programming, a population of candidate solutions, known as \"individuals\" is evolved over multiple generations using principles of genetic variation and selection. The fitness function is a measure of how well a particular individual--a potential solution--fits the data. In Symbolic Regression, the fitness function is typically based on the degree of error between the actual data points and the predicted values generated by the individual's mathematical expression. Crossover and mutation are two key genetic operators used in genetic programming. Crossover involves combining genetic material from two parent individuals to create a new offspring individual, while mutation involves randomly altering the genetic material of an individual in order to introduce new variations. Tournament selection is a common method of selecting individuals for reproduction in genetic programming. In tournament selection, a subset of individuals from the population is chosen at random, and the individual with the highest fitness within that subset is selected for reproduction. In genetic programming, individuals are represented as trees of nodes. Terminal nodes represent input variables or constants, while non-terminal nodes represent mathematical operations or functions [35]. The above experiment has been performed on the dataset that was generated by an earlier-simulated model consisting of SNR values. There are predefined arithmetic functions such as add, sub, mul sin, cos, etc., for the Symbolic Regression. The code is implemented in Python. The SymbolicRegressor class is imported from gplearn.genetic package. Custom-defined functions such as ReLU were defined and added to the function set to provide the algorithm with more flexibility in modeling the data. This can be achieved using the make_function() method. The other parameters that the SymbolicRegressor constructor can take to configure the model are as follows:population_size: The number of individuals (mathematical expressions) in each generation. 2 function_set: The set of functions and terminals that can be used in the mathematical expressions. 3 generations: The maximum number of generations to evolve the population. 4 stopping_criteria: The threshold value for the Mean Absolute Error (MAE) to stop evolution if it falls below this value. 5 p_crossover, p_subtree_mutation, p_hoist_mutation, p_point_mutation: The probabilities of applying crossover, subtree mutation, hoist mutation, and point mutation operations during evolution. 6 max_samples: The maximum proportion of samples to use in each generation during fitness evaluation. 7 verbose: Whether to enable verbose output during evolution. 8 parsimony_coefficient: A coefficient to balance between the goodness of fit and the complexity (parsimony) of the mathematical expressions. 9 random_state: The random seed for reproducibility. These parameters allow us to customize the SymbolicRegressor model to fit the specific needs. For example, one can increase the population_size to improve the accuracy of the model, or these values could also be reduced generations to speed up the training process.