Simulation Results for varying number of maximum iterations

This notebook shows BER and Sum Capacity results for different IA algorithms when the maximum number of allowed iterations is limited. Note that the algorithm might run less iterations than the allowed maximum if the precoders do not change significantly from one iteration to the next one. The maximum number of allowed iterations vary from 5 to 60, except for the closed form algorithm, which is not iterative. The solid lines indicate the BER or Sum Capacity in the left axis, while the dashed lines indicate the mean number of iterations that algorithm used.

Let's perform some initializations.

First we enable the "inline" mode for plots.


In [ ]:
%pylab inline

Now we import some modules we use and add the PyPhysim to the python path.


In [ ]:
import sys
sys.path.append("/home/darlan/cvs_files/pyphysim")
# xxxxxxxxxx Import Statements xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
from pyphysim.simulations.core import SimulationRunner, SimulationParameters, SimulationResults, Result
from pyphysim.comm import modulators, channels
from pyphysim.util.conversion import dB2Linear
from pyphysim.util import misc
# from pyphysim.ia import ia
import numpy as np
from pprint import pprint
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Now we set the transmit parameters and load the simulation results from the file corresponding to those transmit parameters.


In [ ]:
# xxxxx Parameters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#params = SimulationParameters.load_from_config_file('ia_config_file.txt')
K = 3
Nr = 3
Nt = 3
Ns = 2
M = 4
modulator = "PSK"
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# xxxxx Results base name xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
base_name = 'results_{M}-{modulator}_{Nr}x{Nt}_({Ns})_MaxIter_[5_(5)_120]'.format(M=M, modulator=modulator, Nr=Nr, Nt=Nt, Ns=Ns)
base_name_no_iter = 'results_{M}-{modulator}_{Nr}x{Nt}_({Ns})'.format(M=M, modulator=modulator, Nr=Nr, Nt=Nt, Ns=Ns)  # Used only for the closed form algorithm, which is not iterative
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
alt_min_results = SimulationResults.load_from_file(
    'ia_alt_min_{0}.pickle'.format(base_name))
closed_form_results = SimulationResults.load_from_file(
    'ia_closed_form_{0}.pickle'.format(base_name_no_iter))
# closed_form_first_results = SimulationResults.load_from_file(
#     'ia_closed_form_first_init_{0}.pickle'.format(base_name))
max_sinrn_results = SimulationResults.load_from_file(
    "ia_max_sinr_{0}_['random'].pickle".format(base_name))
# min_leakage_results = SimulationResults.load_from_file(
#     'ia_min_leakage_{0}.pickle'.format(base_name))
mmse_results = SimulationResults.load_from_file(
    "ia_mmse_{0}_['random'].pickle".format(base_name))
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Let's define helper methods to get mean number of IA iterations from a simulation results object.


In [ ]:
# Helper function to get the number of repetitions for a given set of transmit parameters
def get_num_runned_reps(sim_results_object, fixed_params=dict()):
    all_runned_reps = np.array(sim_results_object.runned_reps)
    indexes = sim_results_object.params.get_pack_indexes(fixed_params)
    return all_runned_reps[indexes]

# Helper function to get the number of IA runned iterations for a given set of transmit parameters
def get_num_mean_ia_iterations(sim_results_object, fixed_params=dict()):
    return sim_results_object.get_result_values_list('ia_runned_iterations', fixed_params)

Get the SNR values from the simulation parameters object.


In [ ]:
SNR_alt_min = np.array(alt_min_results.params['SNR'])
SNR_closed_form = np.array(closed_form_results.params['SNR'])
SNR_max_SINR = np.array(max_sinrn_results.params['SNR'])
# SNR_min_leakage = np.array(min_leakage_results.params['SNR'])
SNR_mmse = np.array(mmse_results.params['SNR'])

Define a function that we can call to plot the BER. This function will plot the BER for all SNR values for the four IA algorithms, given the desired "max_iterations" parameter value.


In [ ]:
def plot_ber(max_iterations, ax=None):
    ber_alt_min = alt_min_results.get_result_values_list(
        'ber',
        fixed_params={'max_iterations': max_iterations})
    ber_CF_alt_min = alt_min_results.get_result_values_confidence_intervals(
        'ber',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    ber_errors_alt_min = np.abs([i[1] - i[0] for i in ber_CF_alt_min])

    ber_closed_form = closed_form_results.get_result_values_list(
        'ber',
        fixed_params={'max_iterations': max_iterations})
    ber_CF_closed_form = closed_form_results.get_result_values_confidence_intervals(
        'ber',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    ber_errors_closed_form = np.abs([i[1] - i[0] for i in ber_CF_closed_form])

    # ber_closed_form_first = closed_form_first_results.get_result_values_list('ber')
    # ber_CF_closed_form_first = closed_form_first_results.get_result_values_confidence_intervals('ber', P=95)
    # ber_errors_closed_form_first = np.abs([i[1] - i[0] for i in ber_CF_closed_form_first])

    ber_max_sinr = max_sinrn_results.get_result_values_list(
        'ber',
        fixed_params={'max_iterations': max_iterations})
    ber_CF_max_sinr = max_sinrn_results.get_result_values_confidence_intervals(
        'ber',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    ber_errors_max_sinr = np.abs([i[1] - i[0] for i in ber_CF_max_sinr])

    # ber_min_leakage = min_leakage_results.get_result_values_list('ber')
    # ber_CF_min_leakage = min_leakage_results.get_result_values_confidence_intervals('ber', P=95)
    # ber_errors_min_leakage = np.abs([i[1] - i[0] for i in ber_CF_min_leakage])

    ber_mmse = mmse_results.get_result_values_list(
        'ber',
        fixed_params={'max_iterations': max_iterations})
    ber_CF_mmse = mmse_results.get_result_values_confidence_intervals(
        'ber',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    ber_errors_mmse = np.abs([i[1] - i[0] for i in ber_CF_mmse])

    if ax is None:
        fig, ax = plt.subplots(nrows=1, ncols=1)
    ax.errorbar(SNR_alt_min, ber_alt_min, ber_errors_alt_min, fmt='-r*', elinewidth=2.0, label='Alt. Min.')
    ax.errorbar(SNR_closed_form, ber_closed_form, ber_errors_closed_form, fmt='-b*', elinewidth=2.0, label='Closed Form')
    ax.errorbar(SNR_max_SINR, ber_max_sinr, ber_errors_max_sinr, fmt='-g*', elinewidth=2.0, label='Max SINR')
    # ax.errorbar(SNR, ber_min_leakage, ber_errors_min_leakage, fmt='-k*', elinewidth=2.0, label='Min Leakage.')
    ax.errorbar(SNR_mmse, ber_mmse, ber_errors_mmse, fmt='-m*', elinewidth=2.0, label='MMSE.')

    ax.set_xlabel('SNR')
    ax.set_ylabel('BER')
    title = 'BER for Different Algorithms ({max_iterations} Max Iterations)\nK={K}, Nr={Nr}, Nt={Nt}, Ns={Ns}, {M}-{modulator}'.replace("{max_iterations}", str(max_iterations))
    ax.set_title(title.format(**alt_min_results.params.parameters))

    ax.set_yscale('log')
    leg = ax.legend(fancybox=True, shadow=True, loc='lower left', bbox_to_anchor=(0.01, 0.01), ncol=4)
    ax.grid(True, which='both', axis='both')
    
    # Lets plot the mean number of ia iterations
    ax2 = ax.twinx()
    mean_alt_min_ia_terations = get_num_mean_ia_iterations(alt_min_results, {'max_iterations': max_iterations})
    mean_max_sinrn_ia_terations = get_num_mean_ia_iterations(max_sinrn_results, {'max_iterations': max_iterations})
    mean_mmse_ia_terations = get_num_mean_ia_iterations(mmse_results, {'max_iterations': max_iterations})
    ax2.plot(SNR_alt_min, mean_alt_min_ia_terations, '--r*')
    ax2.plot(SNR_max_SINR, mean_max_sinrn_ia_terations, '--g*')
    ax2.plot(SNR_mmse, mean_mmse_ia_terations, '--m*')
    
    # Horizontal line with the max alowed ia iterations
    ax2.hlines(max_iterations, SNR_alt_min[0], SNR_alt_min[-1], linestyles='dashed')
    ax2.set_ylim(0, max_iterations*1.1)
    ax2.set_ylabel('IA Mean Iterations')

    # Set the X axis limits
    ax.set_xlim(SNR_alt_min[0], SNR_alt_min[-1])
    # Set the Y axis limits
    ax.set_ylim(1e-6, 1)

Plot the BER

We can create a 4x4 grids if plots and call the plot_ber function to plot in each subplot.


In [ ]:
fig, ax = subplots(2,2,figsize=(20,15))
plot_ber(5, ax[0,0])
plot_ber(10, ax[0,1])
plot_ber(15, ax[1,0])
plot_ber(20, ax[1,1])

In [ ]:
fig, ax = subplots(2,2,figsize=(20,15))
plot_ber(25, ax[0,0])
plot_ber(30, ax[0,1])
plot_ber(35, ax[1,0])
plot_ber(40, ax[1,1])

In [ ]:
fig, ax = subplots(2,2,figsize=(20,15))
plot_ber(45, ax[0,0])
plot_ber(50, ax[0,1])
plot_ber(55, ax[1,0])
plot_ber(60, ax[1,1])

Plot the Capacity


In [ ]:
def plot_capacity(max_iterations, ax=None):
    # xxxxx Plot Sum Capacity (all) xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    sum_capacity_alt_min = alt_min_results.get_result_values_list(
        'sum_capacity',
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_CF_alt_min = alt_min_results.get_result_values_confidence_intervals(
        'sum_capacity',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_errors_alt_min = np.abs([i[1] - i[0] for i in sum_capacity_CF_alt_min])

    sum_capacity_closed_form = closed_form_results.get_result_values_list(
        'sum_capacity',
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_CF_closed_form = closed_form_results.get_result_values_confidence_intervals(
        'sum_capacity',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_errors_closed_form = np.abs([i[1] - i[0] for i in sum_capacity_CF_closed_form])

    sum_capacity_max_sinr = max_sinrn_results.get_result_values_list(
        'sum_capacity',
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_CF_max_sinr = max_sinrn_results.get_result_values_confidence_intervals(
        'sum_capacity',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_errors_max_sinr = np.abs([i[1] - i[0] for i in sum_capacity_CF_max_sinr])

    # sum_capacity_min_leakage = min_leakage_results.get_result_values_list('sum_capacity')
    # sum_capacity_CF_min_leakage = min_leakage_results.get_result_values_confidence_intervals('sum_capacity', P=95)
    # sum_capacity_errors_min_leakage = np.abs([i[1] - i[0] for i in sum_capacity_CF_min_leakage])

    sum_capacity_mmse = mmse_results.get_result_values_list(
        'sum_capacity',
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_CF_mmse = mmse_results.get_result_values_confidence_intervals(
        'sum_capacity',
        P=95,
        fixed_params={'max_iterations': max_iterations})
    sum_capacity_errors_mmse = np.abs([i[1] - i[0] for i in sum_capacity_CF_mmse])

    if ax is None:
        fig, ax = plt.subplots(nrows=1, ncols=1)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ax.errorbar(SNR_alt_min, sum_capacity_alt_min, sum_capacity_errors_alt_min, fmt='-r*', elinewidth=2.0, label='Alt. Min.')
    ax.errorbar(SNR_closed_form, sum_capacity_closed_form, sum_capacity_errors_closed_form, fmt='-b*', elinewidth=2.0, label='Closed Form')
    ax.errorbar(SNR_max_SINR, sum_capacity_max_sinr, sum_capacity_errors_max_sinr, fmt='-g*', elinewidth=2.0, label='Max SINR')
    # ax.errorbar(SNR, sum_capacity_min_leakage, sum_capacity_errors_min_leakage, fmt='-k*', elinewidth=2.0, label='Min Leakage.')
    ax.errorbar(SNR_mmse, sum_capacity_mmse, sum_capacity_errors_mmse, fmt='-m*', elinewidth=2.0, label='MMSE.')
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    ax.set_xlabel('SNR')
    ax.set_ylabel('Sum Capacity')
    title = 'Sum Capacity for Different Algorithms ({max_iterations} Max Iterations)\nK={K}, Nr={Nr}, Nt={Nt}, Ns={Ns}, {M}-{modulator}'.replace("{max_iterations}", str(max_iterations))
    ax.set_title(title.format(**alt_min_results.params.parameters))

    #leg = ax.legend(fancybox=True, shadow=True, loc=2)
    leg = ax.legend(fancybox=True, shadow=True, loc='lower right', bbox_to_anchor=(0.99, 0.01), ncol=4)
    
    ax.grid(True, which='both', axis='both')
    
    # Lets plot the mean number of ia iterations
    ax2 = ax.twinx()
    mean_alt_min_ia_terations = get_num_mean_ia_iterations(alt_min_results, {'max_iterations': max_iterations})
    mean_max_sinrn_ia_terations = get_num_mean_ia_iterations(max_sinrn_results, {'max_iterations': max_iterations})
    mean_mmse_ia_terations = get_num_mean_ia_iterations(mmse_results, {'max_iterations': max_iterations})
    ax2.plot(SNR_alt_min, mean_alt_min_ia_terations, '--r*')
    ax2.plot(SNR_max_SINR, mean_max_sinrn_ia_terations, '--g*')
    ax2.plot(SNR_mmse, mean_mmse_ia_terations, '--m*')
    
    # Horizontal line with the max alowed ia iterations
    ax2.hlines(max_iterations, SNR_alt_min[0], SNR_alt_min[-1], linestyles='dashed')
    ax2.set_ylim(0, max_iterations*1.1)
    ax2.set_ylabel('IA Mean Iterations')

    # Set the X axis limits
    ax.set_xlim(SNR_alt_min[0], SNR_alt_min[-1])
    # Set the Y axis limits
    #ax.set_ylim(1e-6, 1)

In [ ]:
fig, ax = subplots(2,2,figsize=(20,15))
plot_capacity(5, ax[0,0])
plot_capacity(10, ax[0,1])
plot_capacity(15, ax[1,0])
plot_capacity(20, ax[1,1])

In [ ]:
fig, ax = subplots(2,2,figsize=(20,15))
plot_capacity(25, ax[0,0])
plot_capacity(30, ax[0,1])
plot_capacity(35, ax[1,0])
plot_capacity(40, ax[1,1])

In [ ]:
fig, ax = subplots(2,2,figsize=(20,15))
plot_capacity(45, ax[0,0])
plot_capacity(50, ax[0,1])
plot_capacity(55, ax[1,0])
plot_capacity(60, ax[1,1])