<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Initializations
Step1:  Set the parameters, create the cluster and the channels, etc
Step2:  Calculate the distances between each user and each base station
Step3:  Plot the distances
Step4:  Calculate the Transmit power of each user
Step5:  Path Loss of the Interference Links relative to the direct link
Step6:  Question
Step7:  However, notice that the relative path loss is only one side of the coint. We still need to account the transmit power of each interfering base station when compared with the transmit power of our own base station. That is, if the relative path loss to some interference link is 25dB, but that particular base station transmit with 10dB more power than our own base station then the relative interference power of that link when compared with the desired signal would be 15dB.
Find the IA Solution
Step8:  Some of the precoders may have 0 energy.
Step9:  Pos Processing SINR for each Stream
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
from ipywidgets.widgets import Image
from IPython.display import display, display_svg, display_png
# xxxxxxxxxx Add the parent folder to the python path. xxxxxxxxxxxxxxxxxxxx
import sys
parent_dir = "../"
sys.path.append(parent_dir)
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxx Import Statements xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
from time import time
from time import sleep
import numpy as np
from pprint import pprint
from matplotlib import pyplot as plt
from pyphysim.simulations.runner import SimulationRunner
from pyphysim.simulations.parameters import SimulationParameters
from pyphysim.simulations.results import SimulationResults, Result
from pyphysim.simulations.simulationhelpers import simulate_do_what_i_mean
from pyphysim.simulations.runner import get_common_parser
from pyphysim.modulators.fundamental import PSK
from pyphysim.channels import pathloss
from pyphysim.channels import multiuser
from pyphysim.util.conversion import dB2Linear, linear2dB
from pyphysim.cell.cell import Cluster
from pyphysim.util import misc
from pyphysim.util.conversion import dBm2Linear
from pyphysim.ia import algorithms
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Explanation: Initializations: Skip to the next section
<span style="color:red;">TODO</span>: Fix problems
End of explanation
multiUserChannel = multiuser.MultiUserChannelMatrix()
#ia_solver = algorithms.MMSEIASolver(multiUserChannel)
ia_solver = algorithms.MaxSinrIASolver(multiUserChannel)
#ia_solver = algorithms.AlternatingMinIASolver(multiUserChannel)
ia_solver.max_iterations = 500
modulator = PSK(4)
include_path_loss_bool = True
M = 4
NSymbs = 100
K = 19
Nr = 4
Nt = 8
Ns = 2
SNR = 30.0
users_per_cell = 1
# Cluter variables
cell_radius = 1.0
# Dependent parameters
#noise_var = 1 / dB2Linear(SNR)
noise_var = dBm2Linear(-116.4)
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxx Create the cluster of cells xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cluster = Cluster(cell_radius=cell_radius, num_cells=19)
cluster.create_wrap_around_cells(include_users_bool=True)
cluster.add_random_users(cell_ids=range(1,20), num_users=users_per_cell)
#cluster.add_border_users(cell_ids=range(1,20), angles=0, ratios=0.01)
cluster.figsize = (7,7)
cluster.fill_face_bool = True
cluster.fill_opacity = 0.3
cluster
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Explanation: Set the parameters, create the cluster and the channels, etc
End of explanation
multiUserChannel.randomize(Nr, Nt, K)
if include_path_loss_bool is True:
    # xxxxxxxxxx Calculate the pathloss for each link xxxxxxxxxxxxxxxxxxxxx
    dists = cluster.calc_dist_all_users_to_each_cell()
    #pl_obj = pathloss.PathLossFreeSpace()
    pl_obj = pathloss.PathLoss3GPP1()
    #pl_obj = pathloss.PathLossOkomuraHata()
    # Calculate the path loss in linear scale
    pl = pl_obj.calc_path_loss(dists)
    #pl = np.eye(19)
    multiUserChannel.set_pathloss(pl)
else:
    # Path loss will be equal to 1.0 for all links
    pl = np.ones([K,K])
    multiUserChannel.set_pathloss(None)
Explanation: Calculate the distances between each user and each base station
End of explanation
# fig, axs = plt.subplots(10,2, figsize=(12,40))
# for row in range(10):
#     for col in range(2):
#         index = 2 * row + col
#         if index > 18:
#             break
# #         print "{0}: {1}x{2}".format(index, row, col)
#         axs[row, col].set_xlim([0, 20])
#         axs[row, col].grid()
#         axs[row, col].plot(range(1,20), dists[index])
#         axs[row, col].plot(index+1, dists[index][index], 'or')
#         axs[row, col].xaxis.set_ticks(np.arange(1,20))
# plt.show()
Explanation: Plot the distances
End of explanation
# Calculate the transmit power of each user
snr = dB2Linear(SNR)
Pt = snr * noise_var/pl.diagonal()
Explanation: Calculate the Transmit power of each user
End of explanation
pl_dB = -linear2dB(pl)
np.set_printoptions(precision=1, linewidth=140)
for index in range(19):
    pl_dB[index] = pl_dB[index] - pl_dB[index][index]
print('Relative Direct Channel Path Loss:\n{0}'.format(pl_dB.diagonal()))
print('Relative Max Path Loss:\n{0}'.format(pl_dB.max(axis=1)))
print('Relative Min Path Loss:\n{0}'.format(np.sort(pl_dB, axis=1)[:,1]))
print()
np.set_printoptions(precision=4, linewidth=120)
# print np.mean(np.sort(pl_dB, axis=1)[:,1])
# print np.mean(pl_dB.max(axis=1))
Explanation: Path Loss of the Interference Links relative to the direct link
End of explanation
[(sum(pl_dB[i] < 30) - 1) for i in range(19)]
Explanation: Question: How many interference links are strong enough?
First we need to ask ourselves what is a good measurement that we can use to say that a interference link is strong enough or not. The easiest one is probably the path loss.
If we count the number of interference links that have a relative path loss when compared with the direct channel of less than 30dB we get
End of explanation
noise_var
assert abs(ia_solver.noise_var - noise_var) < 1e-12
ia_solver.clear()
runned_reps = ia_solver.solve(Ns=Ns, P=Pt)
print(runned_reps)
Explanation: However, notice that the relative path loss is only one side of the coint. We still need to account the transmit power of each interfering base station when compared with the transmit power of our own base station. That is, if the relative path loss to some interference link is 25dB, but that particular base station transmit with 10dB more power than our own base station then the relative interference power of that link when compared with the desired signal would be 15dB.
Find the IA Solution
End of explanation
data = []
for f in ia_solver.full_F:
    data.append(np.linalg.norm(f, 'fro')**2)
    print(data[-1])
    
print
data = np.array(data)
#print("Number of non zero links: {0}".format(len(data[data > 1e-3])))
print("Sum Capacity: {0}\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".format(ia_solver.calc_sum_capacity()))
Explanation: Some of the precoders may have 0 energy.
End of explanation
print("Input SNR: {0}".format(SNR))
print("Post-processing SINRs")
for v in ia_solver.calc_SINR_in_dB():
    print(v)
# # If any of the Nr, Nt or Ns variables were integers (meaning all
# # users have the same value) we will convert them by numpy arrays
# # with correct size (K).
# Nr = ia_solver.Nr
# Nt = ia_solver.Nt
# Ns = ia_solver.Ns
# cumNs = np.cumsum(ia_solver.Ns)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # inputData has the data of all users (vertically stacked)
# inputData = np.random.randint(0, M, [np.sum(Ns), NSymbs])
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # modulatedData has the data of all users (vertically stacked)
# modulatedData = modulator.modulate(inputData)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxxxxxxx Perform the Interference Alignment xxxxxxxxxxxxxxxxxxx
# # Split the data. transmit_signal will be a list and each element
# # is a numpy array with the data of a user
# transmit_signal = np.split(modulatedData, cumNs[:-1])
# transmit_signal_precoded = map(np.dot, ia_solver.full_F, transmit_signal)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# multi_user_channel = ia_solver._multiUserChannel
# # received_data is an array of matrices, one matrix for each receiver.
# #import pudb; pudb.set_trace()  ## DEBUG ##
# received_data = multi_user_channel.corrupt_data(
#     transmit_signal_precoded, noise_var)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Perform the Interference Cancelation xxxxxxxxxxxxxxxxxxxxxx
# received_data_no_interference = map(np.dot,
#                                     ia_solver.full_W_H, received_data)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Demodulate Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# received_data_no_interference = np.vstack(received_data_no_interference)
# demodulated_data = modulator.demodulate(received_data_no_interference)
# # demodulated_data = map(modulator.demodulate, received_data_no_interference)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
# symbolErrors = np.sum(inputData != demodulated_data)
# bitErrors = misc.count_bit_errors(inputData, demodulated_data)
# numSymbols = inputData.size
# numBits = inputData.size * modulators.level2bits(M)
# ia_cost = ia_solver.get_cost()
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # xxxxxxxxxx Calculates the Sum Capacity xxxxxxxxxxxxxxxxxxxxxxxxxx
# sirn_all_k = ia_solver.calc_SINR()
# calc_capacity = lambda sirn: np.sum(np.log2(1 + sirn))
# # Array with the sum capacity of each user
# sum_capacity = map(calc_capacity, sirn_all_k)
# # Total sum capacity
# total_sum_capacity = np.sum(sum_capacity)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# #xxxxxxxxxx Number of iterations of the IA algorithm xxxxxxxxxxxxxx
# ia_runned_iterations = ia_solver.runned_iterations
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # Print the results
# print("SumCapacity: {0}".format(total_sum_capacity))
# print("BER: {0}".format(float(bitErrors)/numBits))
# # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# symbolErrorsResult = Result.create(
#     "symbol_errors", Result.SUMTYPE, symbolErrors)
# numSymbolsResult = Result.create(
#     "num_symbols", Result.SUMTYPE, numSymbols)
# bitErrorsResult = Result.create("bit_errors", Result.SUMTYPE, bitErrors)
# numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)
# berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits,
#                           accumulate_values=False)
# serResult = Result.create(
#     "ser", Result.RATIOTYPE, symbolErrors, numSymbols, accumulate_values=False)
# ia_costResult = Result.create(
#     "ia_cost", Result.RATIOTYPE, ia_cost, 1, accumulate_values=False)
# sum_capacityResult = Result.create(
#     "sum_capacity", Result.RATIOTYPE, total_sum_capacity, 1,
#     accumulate_values=False)
# ia_runned_iterationsResult = Result.create(
#     "ia_runned_iterations", Result.RATIOTYPE, ia_runned_iterations, 1, accumulate_values=False)
# #import pudb; pudb.set_trace()  ## DEBUG ##
# simResults = SimulationResults()
# simResults.add_result(symbolErrorsResult)
# simResults.add_result(numSymbolsResult)
# simResults.add_result(bitErrorsResult)
# simResults.add_result(numBitsResult)
# simResults.add_result(berResult)
# simResults.add_result(serResult)
# simResults.add_result(ia_costResult)
# simResults.add_result(sum_capacityResult)
# simResults.add_result(ia_runned_iterationsResult)
# # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# # return simResults
Explanation: Pos Processing SINR for each Stream
End of explanation
<END_TASK>