## 4 Rate Optimization
### Initialization  
The phases of 500 channel elements of V for every column are examined and a suitable value of \(\theta\) element corresponding to that column is chosen so that, for most channel elements, \(\mathbf{V}\times\mathbf{\theta}\) lies in the I or II quadrant. If this happens, there will be constructive interference, which potentially leads to beamforming among the channel elements leading to higher rates. The initialization algorithm is illustrated in Algorithm 1. ```
1:Input: \(\mathbf{V}\), \(\mathbf{V}\), \(\mathbf{V}^{\prime}\), \(\mathbf{V}^{\prime}\), \(\mathbf{V}^{\prime}\), \(



Cartesian plane is hard, and hence, we use another algorithm on top of this to get better rates for the NLOS users. ```
Result: Initial solution of \(\theta\) foreach\(column\) in \(V\)do \(count1\gets 0\); \(count2\gets 0\) foreachrow in \(V\)do if\(V(row,column)\) in \(I\) or \(II\) quadrantthen  increment\(count1\) else  increment\(count2\)  end if  end foreach\(\theta(column)\leftarrow(count1>count2)\)? \(1\): \(-1\)  end foreach
```
**Algorithm 1**Initialization algorithm

### Further Optimization

The \(\theta\) vector obtained in the previous step is the input in this stage. The rows of \(\mathbf{V}\) are arranged in descending order, based on the sum of the square of the magnitude of the elements. For every row of \(\mathbf{V}\) which corresponds to a particular subcarrier, a temporary IRS configuration \(\mathbf{\theta_{2}}\) is calculated using the principles of Algorithm 1. A greedy solution is then used to improve the rate further. The number of steps in the greedy solution is kept high in the initial rows (which corresponds to higher magnitude) and is gradually decreased to cater to the time complexity. This approach is illustrated in Algorithm 2. ```
Input:\(\theta\) - Output of Algorithm 1 Result:\(\theta_{1}\) - Final optimized solution foreachrow in \(V\)do \(subcarriers(row)\leftarrow\sum_{j=1}^{4096}|V(i,j)|^{2}\) end foreach\([\sim,sorted\_subcarrier\_indices]\leftarrow\text{sort}(subcarriers)\)\(\theta_{1}\leftarrow\theta\) foreachrow in \(V\)do \(\text{index}\leftarrowsorted\_subcarrier\_indices(row)\) foreach\(column\) in \(V\)do if\(V(row,column)\) in \(I\) or \(II\) quadrantthen \(\theta_{2}(column)\gets 1\) else \(\theta_{2}(column)\leftarrow-1\)  end foreach\(max\_iter\leftarrow\max(501-row,200)\) repeat \(\text{ran}\leftarrow\text{random number in }[1,4096]\) if\(\theta_{2}(ran)\)\(l\)= \(\theta_{1}(ran)\)then \(\theta_{3}\leftarrow\theta_{1}\) \(\theta_{3}(ran)\leftarrow\text{flip\_element}(\theta_{3}(ran))\) \(r1\leftarrow\text{find\_rate}(\theta_{1})\); \(r2\leftarrow\text{find\_rate}(\theta_{3})\) \(\theta_{1}(ran)\leftarrow(r1<r2)\)? \(\theta_{2}(ran)\): \(\theta_{1}(ran)\)  end if until\(max\_iter\);  end foreach
```
**Algorithm 2**Further optimization

### Further Optimization

The \(\theta\) vector obtained in the previous step is the input in this stage. The rows of \(\mathbf{V}\) are arranged in descending order, based on the sum of the square of the magnitude of the elements. For every row of \(\mathbf{V}\) which corresponds to a particular subcarrier, a temporary IRS configuration \(\mathbf{\theta_{2}}\) is calculated using the principles of Algorithm 1. A greedy solution is then used to improve the rate further. The number of steps in the greedy solution is kept high in the initial rows (which corresponds to higher magnitude) and is gradually decreased to cater to the time complexity. This approach is illustrated in Algorithm 2.