Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending the project to include NOMA signal detection #11

Open
MAbuain17 opened this issue Feb 28, 2024 · 12 comments
Open

Extending the project to include NOMA signal detection #11

MAbuain17 opened this issue Feb 28, 2024 · 12 comments

Comments

@MAbuain17
Copy link

Hi, I am actively working to extend this to include also the leading NOMA detection along with MIMO. I have QUBO formulation from one of the research papers but I have no idea to implement it using your libraries. can you help me?
2301.03872_3.pdf

@jackraymond
Copy link

jackraymond commented Mar 9, 2024

This paper cites [2] S. Kasi and K. Jamieson, “Towards quantum belief propagation for LDPC
decoding in wireless networks,” 26th Annu. Int. Conf. Mobile Comput.
Netw., London, UK, pp. 1-14, Sep. 2020.
for its QUBO representation, but this seems to be a miscitation (related problem of LDPC). The intended paper is I think:
https://dl.acm.org/doi/10.1145/3341302.3342072 , which has the same deriviation, and is the paper we cite in the code base. I think MIMO and NOMA are different names for the same thing.

See equation (1) and (2) from the NOMA paper you cite. We have codes to support mimo, which are based on the same formulation. Our code should support abitrary s (called F, the channel, in our code) and y (the signal), create a QUBO appropriate for maximum likelihood (subject to the spin-encoding described in cited papers), and perform transforms from symbols to spins. Symbols need to be from the BPSK, QPSK, 16QAM or 64QAM constellations..

@MAbuain17
Copy link
Author

This paper cites [2] S. Kasi and K. Jamieson, “Towards quantum belief propagation for LDPC decoding in wireless networks,” 26th Annu. Int. Conf. Mobile Comput. Netw., London, UK, pp. 1-14, Sep. 2020. for its QUBO representation, but this seems to be a miscitation (related problem of LDPC). The intended paper is I think: https://dl.acm.org/doi/10.1145/3341302.3342072 , which has the same deriviation, and is the paper we cite in the code base. I think MIMO and NOMA are different names for the same thing.

See equation (1) and (2) from the NOMA paper you cite. We have codes to support mimo, which are based on the same formulation. Our code should support abitrary s (called F, the channel, in our code) and y (the signal), create a QUBO appropriate for maximum likelihood (subject to the spin-encoding described in cited papers), and perform transforms from symbols to spins. Symbols need to be from the BPSK, QPSK, 16QAM or 64QAM constellations..

Hi, indeed the citation seems to be mistaken.
however, even though the Maximum Likelihood expression of MIMO and NOMA seems alike, they are 2 distinct concepts.
i have tried to study your code but i have found that it calls functions like dimod.generators.wirless etc, which I can't find.
can you guide me through on how to modify F channel and y signals?
thanks in advance

@jackraymond
Copy link

jackraymond commented Mar 31, 2024

https://github.com/dwavesystems/dimod/blob/63d46298655621f54206ce2d86d20f5baa65fc57/dimod/generators/wireless.py#L540
Construct F as a (num_receiver,num_transmitter) shaped numpy array (Each column is h_{k} according to equation (1))
Construct channel_noise as a (num_receiver,1) shaped numpy array (called n in equation (1))
Decide on the modulation (note that constellation values are scaled to integer in the complex and real parts)
Construct transmitted_symbols as a (num_transmitter,1) shaped array (called s in equation (1)). Consistent with the modulation
from dimod.generators.wireless import mimo
bqm = mimo(modulation=modulation, F=F, channel_noise=channel_noise, transmitted_symbols=transmitted_symbols)
should generate an Ising model, the minima of which gives the maximum likelihood (spin-encoded) sequence.

To calculate the bit error rate, you can solve the bqm and then take your best solution (spins_ideal, a numpy array) and compare it to
'spins_ideal = dimod.generators.wireless._symbols_to_bits(transmitted_symbols, modulation=modulation)', which is the transmitted_symbols encoded as spins. I.e. Bit_error_rate = (1 - np.mean(spins_ideal*spins_best))/2. If and only if all the spins in the solution agree with the transmitted values this is zero.

As you mention, NOMA has some domain specific channel features (per Figure 1). A function that generates F accordingly might be appropriate.

@MAbuain17
Copy link
Author

MAbuain17 commented Apr 8, 2024

I have tried to follow your path and have written the following for simple case of 2 users employing BPSK:
`# Define the channel gains
h1 = 0.8 # Channel gain for user 1
h2 = 0.6 # Channel gain for user 2

Construct the channel matrix F

F = np.array([[h1], # Channel gain for user 1
[h2]]) # Channel gain for user 2

Set other parameters

num_receiver = 2
num_transmitter = 1
variance = 0.1

Construct channel_noise as a (num_receiver, 1) shaped numpy array

channel_noise = np.sqrt(variance) * np.random.randn(num_receiver, 1)

Construct transmitted_symbols as a (num_transmitter, 1) shaped array (BPSK modulation)

transmitted_symbols = np.random.choice([-1, 1], size=(num_transmitter, 1))

Generate the Ising model using dimod

bqm = dimod.generators.wireless.mimo(modulation='BPSK', F=F, channel_noise=channel_noise, transmitted_symbols=transmitted_symbols)

Print the generated Ising model

print(f"BQM has {len(bqm)} variables with {len(bqm.quadratic)} quadratic interactions.")

sampler = FixedEmbeddingComposite(qpu, embedding)

Sample the Ising model

sampleset = sampler.sample(bqm,
num_reads=30,
annealing_time=200,
chain_strength=-0.13 * min(bqm.linear.values()),
label='Notebook - Coordinated Multipoint')

Get the best solution

sample = sampleset.first.sample
spins_best = np.array(list(sample.values()))

3. Convert transmitted symbols to spins

spins_ideal = dimod.generators.wireless._symbols_to_bits(transmitted_symbols, modulation='BPSK')

Calculate the bit error rate (assuming spins_ideal is already calculated)

bit_error_rate = (1 - np.mean(spins_ideal * spins_best)) / 2

Print the bit error rate

print("Bit Error Rate:", bit_error_rate)`

everytime i run this i get this result:
BQM has 1 variables with 0 quadratic interactions. Bit Error Rate: 0.0
shouldn't the BER change every run? since different samples are taken.

Thanks alot for your time helping me, i really appreciate your support.

@MAbuain17
Copy link
Author

@jackraymond also, i forgot to ask you how to do embedding for my problem, I tried to read the documentation on DWave's website but i feel kind of lost. i am grateful for your help :)

@jackraymond
Copy link

A 1 transmitter problem has no interference and so the decoding problem is easy, subject to noise. Your noise here is also small (compared to your gain). As such, I think it makes sense that you see a bit error rate of zero.
If you move to more complicated problems, or raise the noise (root variance) to be larger than the gain, you should see the bit error rate depart from zero.

If F is dense, then you will need a clique embedding. The quickest way to start sampling is to use https://docs.ocean.dwavesys.com/projects/system/en/stable/_modules/dwave/system/samplers/clique.html the DWaveCliqueSampler in place of FixedEmbeddingComposite.
If F has some special structure (like in the notebook example CoMP) then it makes sense to find a more efficient embedding and feed it to FixedEmbeddingComposite.

@MAbuain17
Copy link
Author

MAbuain17 commented Apr 11, 2024

you are right, I have flipped the num# of Rx, Tx it should be the reverse. the weird thing is that if you notice the {len(bqm)} variables with {len(bqm.quadratic)} quadratic interactions. gives 'BQM has 1 variables with 0 quadratic interactions' which is not correct i think..
as for embedding you are right, but I thought that as I am using the same QUBO/ising model the fixed embedding will be the same. I have read in your documentation (Dwave website) EmbeddingComposite(qpu) that will automatically generate the appropriate embedding.
I have given another shot using QPSK with 4 users with the above embedding:

`import numpy as np
from dimod.generators.wireless import mimo
from dwave.system import DWaveSampler, EmbeddingComposite
import dimod

Define the number of receivers and transmitters

num_receiver = 1 # Single base station
num_transmitter = 4 # Number of end-users

Define the transmit power (assumed to be the same for all users)

P = 1.0

Define the path-loss exponent

tau = 2

Define the distances of end-users from the base station

distances = np.array([50, 75, 100, 120])

Construct the channel coefficients (h_k) based on the given model

h_tilde = np.random.randn(num_transmitter) + 1j * np.random.randn(num_transmitter)
h = h_tilde / np.sqrt(distances ** tau)

Construct F as a (num_receiver, num_transmitter) shaped numpy array

F = np.sqrt(P) * h.reshape(1, -1)

Define the noise variance

sigma_n_squared = 0.1

Construct channel_noise as a (num_receiver, 1) shaped numpy array

channel_noise = np.sqrt(sigma_n_squared) * (np.random.randn(num_receiver, 1) + 1j * np.random.randn(num_receiver, 1))

Decide on the modulation (example: QPSK)

modulation = 'QPSK'

Construct transmitted_symbols as a (num_transmitter, 1) shaped array

if modulation == 'QPSK':
# QPSK modulation: constellation points scaled to integers
constellation = np.array([1 + 1j, -1 + 1j, -1 - 1j, 1 - 1j])
transmitted_symbols = np.random.choice(constellation, size=(num_transmitter, 1))
else:
# Add other modulation schemes as needed
raise ValueError(f"Unsupported modulation: {modulation}")

Generate the Ising model using mimo function

bqm = mimo(modulation=modulation, F=F, channel_noise=channel_noise, transmitted_symbols=transmitted_symbols)
print(f"BQM has {len(bqm)} variables with {len(bqm.quadratic)} quadratic interactions.")

Set up the QPU sampler

qpu = DWaveSampler()

Create the EmbeddingComposite sampler

sampler = EmbeddingComposite(qpu)

Solve the BQM using the EmbeddingComposite sampler

sampleset = sampler.sample(bqm,
num_reads=30,
annealing_time=200,
chain_strength=-0.13*min(bqm.linear.values()),
label='Noma')

Get the best solution (spins) from the sampleset

spins_best = sampleset.first.sample

Convert the transmitted symbols to spins (ideal spins)

spins_ideal = dimod.generators.wireless._symbols_to_bits(transmitted_symbols, modulation=modulation)

Extract the spin values from the best solution dictionary

spins_best_values = np.array(list(spins_best.values()))

Calculate the bit error rate

bit_error_rate = (1 - np.mean(spins_ideal == spins_best_values)) / 2

print(f"Bit Error Rate: {bit_error_rate}")

Calculate the signal power for each user

signal_power = np.abs(h)**2 * P

Calculate the noise power

noise_power = sigma_n_squared

Calculate the SNR for each user (in linear scale)

snr_linear = signal_power / noise_power

Convert the SNR to dB scale

snr_db = 10 * np.log10(snr_linear)

Print the SNR for each user

for i, snr in enumerate(snr_db):
print(f"SNR for User {i+1}: {snr:.2f} dB")`

the code seems to work but gives higher than expected (compared with results in the paper) BER hovering around ~0.25, i have tried to fiddle around with different SNR ( changing Power , pathloss distance , AWGN) but same results, how can i know if i am going on the right track?

also, I noticed the author of the paper mention something about running the same problem many times

The QA method was implemented on the proposed system model using D-Wave’s Advantage QPU [12]. It is important
to mention that the parallelization procedure was used to save the simulation time on the QA computer [3], i.e., 5 instances
of the problem were run at the same time on QPU. Since the 3-user BPSK problem requires only 3 logical qubits, 5 instances would occupy 15 logical qubits.

I know that the solution of QA will differ each run but is it critical to run the simulation many times( the author mentions 380times) and take the average to ensure accurateness?

sorry for the many questions but i don't have anyone else to talk to about it ! can't express my gratitude to your help 👍

@MAbuain17
Copy link
Author

MAbuain17 commented Apr 12, 2024

also, when using CoMP (your demo) for higher modulation schemes (16QAM,64QAM,256QAM), i get this error

`---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~\AppData\Roaming\Python\Python312\site-packages\dwave\embedding\transforms.py:261, in EmbeddedStructure.embed_bqm(self, source_bqm, chain_strength, smear_vartype)
260 try:
--> 261 chain = self[v]
262 except KeyError:

KeyError: 1920

During handling of the above exception, another exception occurred:

MissingChainError Traceback (most recent call last)
Cell In[79], line 3
1 sampler = FixedEmbeddingComposite(qpu, embedding)
----> 3 sampleset = sampler.sample(bqm,
4 num_reads=30,
5 annealing_time=200,
6 chain_strength=-0.13*min(bqm.linear.values()),
7 label='Notebook - Coordinated Multipoint')
9 _ = compare_signals(sampleset, transmitted_symbols)

File ~\AppData\Roaming\Python\Python312\site-packages\dwave\system\composites\embedding.py:499, in LazyFixedEmbeddingComposite.sample(self, bqm, **parameters)
494 embedding = self.find_embedding(source_edgelist, target_edgelist,
495 **embedding_parameters)
497 self._fix_embedding(embedding)
...
266 if len(chain) == 1:
267 # in the case where the chain has length 1, there are no chain quadratic biases,
268 # but we none-the-less want the chain variables to appear in the target_bqm

MissingChainError: chain for 1920 is empty or not contained in this embedding
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...`

the issue also seems to be related to embedding, i tried changing it to clique but it gave error limit of 3xx something.. embedding composite seem to work ( takes alot of time ) but then it throws an error of mismatch in _compare_signals

@jackraymond
Copy link

also, when using CoMP (your demo) for higher modulation schemes (16QAM,64QAM,256QAM), i get this error

`--------------------------------------------------------------------------- KeyError Traceback (most recent call last) File ~\AppData\Roaming\Python\Python312\site-packages\dwave\embedding\transforms.py:261, in EmbeddedStructure.embed_bqm(self, source_bqm, chain_strength, smear_vartype) 260 try: --> 261 chain = self[v] 262 except KeyError:

KeyError: 1920

During handling of the above exception, another exception occurred:

MissingChainError Traceback (most recent call last) Cell In[79], line 3 1 sampler = FixedEmbeddingComposite(qpu, embedding) ----> 3 sampleset = sampler.sample(bqm, 4 num_reads=30, 5 annealing_time=200, 6 chain_strength=-0.13*min(bqm.linear.values()), 7 label='Notebook - Coordinated Multipoint') 9 _ = compare_signals(sampleset, transmitted_symbols)

File ~\AppData\Roaming\Python\Python312\site-packages\dwave\system\composites\embedding.py:499, in LazyFixedEmbeddingComposite.sample(self, bqm, **parameters) 494 embedding = self.find_embedding(source_edgelist, target_edgelist, 495 **embedding_parameters) 497 self._fix_embedding(embedding) ... 266 if len(chain) == 1: 267 # in the case where the chain has length 1, there are no chain quadratic biases, 268 # but we none-the-less want the chain variables to appear in the target_bqm

MissingChainError: chain for 1920 is empty or not contained in this embedding Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...`

the issue also seems to be related to embedding, i tried changing it to clique but it gave error limit of 3xx something.. embedding composite seem to work ( takes alot of time ) but then it throws an error of mismatch in _compare_signals

The embedding is unfortunately specific both to the combination of the modulation scheme and the structure of network, it is BPSK only (as you found).

@jackraymond
Copy link

you are right, I have flipped the num# of Rx, Tx it should be the reverse. the weird thing is that if you notice the {len(bqm)} variables with {len(bqm.quadratic)} quadratic interactions. gives 'BQM has 1 variables with 0 quadratic interactions' which is not correct i think.. as for embedding you are right, but I thought that as I am using the same QUBO/ising model the fixed embedding will be the same. I have read in your documentation (Dwave website) EmbeddingComposite(qpu) that will automatically generate the appropriate embedding. I have given another shot using QPSK with 4 users with the above embedding:

`import numpy as np
from dimod.generators.wireless import mimo
from dwave.system import DWaveSampler, EmbeddingComposite
import dimod

Define the number of receivers and transmitters

num_receiver = 1 # Single base station num_transmitter = 4 # Number of end-users

Define the transmit power (assumed to be the same for all users)

P = 1.0

Define the path-loss exponent

tau = 2

Define the distances of end-users from the base station

distances = np.array([50, 75, 100, 120])

Construct the channel coefficients (h_k) based on the given model

h_tilde = np.random.randn(num_transmitter) + 1j * np.random.randn(num_transmitter) h = h_tilde / np.sqrt(distances ** tau)

Construct F as a (num_receiver, num_transmitter) shaped numpy array

F = np.sqrt(P) * h.reshape(1, -1)

Define the noise variance

sigma_n_squared = 0.1

Construct channel_noise as a (num_receiver, 1) shaped numpy array

channel_noise = np.sqrt(sigma_n_squared) * (np.random.randn(num_receiver, 1) + 1j * np.random.randn(num_receiver, 1))

Decide on the modulation (example: QPSK)

modulation = 'QPSK'

Construct transmitted_symbols as a (num_transmitter, 1) shaped array

if modulation == 'QPSK': # QPSK modulation: constellation points scaled to integers constellation = np.array([1 + 1j, -1 + 1j, -1 - 1j, 1 - 1j]) transmitted_symbols = np.random.choice(constellation, size=(num_transmitter, 1)) else: # Add other modulation schemes as needed raise ValueError(f"Unsupported modulation: {modulation}")

Generate the Ising model using mimo function

bqm = mimo(modulation=modulation, F=F, channel_noise=channel_noise, transmitted_symbols=transmitted_symbols) print(f"BQM has {len(bqm)} variables with {len(bqm.quadratic)} quadratic interactions.")

Set up the QPU sampler

qpu = DWaveSampler()

Create the EmbeddingComposite sampler

sampler = EmbeddingComposite(qpu)

Solve the BQM using the EmbeddingComposite sampler

sampleset = sampler.sample(bqm, num_reads=30, annealing_time=200, chain_strength=-0.13*min(bqm.linear.values()), label='Noma')

Get the best solution (spins) from the sampleset

spins_best = sampleset.first.sample

Convert the transmitted symbols to spins (ideal spins)

spins_ideal = dimod.generators.wireless._symbols_to_bits(transmitted_symbols, modulation=modulation)

Extract the spin values from the best solution dictionary

spins_best_values = np.array(list(spins_best.values()))

Calculate the bit error rate

bit_error_rate = (1 - np.mean(spins_ideal == spins_best_values)) / 2

print(f"Bit Error Rate: {bit_error_rate}")

Calculate the signal power for each user

signal_power = np.abs(h)**2 * P

Calculate the noise power

noise_power = sigma_n_squared

Calculate the SNR for each user (in linear scale)

snr_linear = signal_power / noise_power

Convert the SNR to dB scale

snr_db = 10 * np.log10(snr_linear)

Print the SNR for each user

for i, snr in enumerate(snr_db): print(f"SNR for User {i+1}: {snr:.2f} dB")`

the code seems to work but gives higher than expected (compared with results in the paper) BER hovering around ~0.25, i have tried to fiddle around with different SNR ( changing Power , pathloss distance , AWGN) but same results, how can i know if i am going on the right track?

also, I noticed the author of the paper mention something about running the same problem many times

The QA method was implemented on the proposed system model using D-Wave’s Advantage QPU [12]. It is important
to mention that the parallelization procedure was used to save the simulation time on the QA computer [3], i.e., 5 instances
of the problem were run at the same time on QPU. Since the 3-user BPSK problem requires only 3 logical qubits, 5 instances would occupy 15 logical qubits.

I know that the solution of QA will differ each run but is it critical to run the simulation many times( the author mentions 380times) and take the average to ensure accurateness?

sorry for the many questions but i don't have anyone else to talk to about it ! can't express my gratitude to your help 👍

I copy pasted some of this code to run, but there are missing dependencies. Regardless, I dont have much time to reproduce results.
With 1 transmitter, in the 'Ising' Formulation, the quadratic term J is zero (and the field h is non-zero). Hence len(bqm.quadratic) == 0. In the QUBO formulation it would be 1, perhaps this is the source of the confusion. The two formulations are equivalent.
I'm not sure why you are seeing 25% while the authors see smaller values. It is likely that the authors used a different chain strength for example (probably the default, I can't think of a reason 0.13 would be better than the default in this scenario). Aside from that difference, a careful reading of the paper is necessary to understand formulation differences; and if you continue to see a difference maybe contact the authors for reproducible code.
They seem to be submitting multiple (M) jobs in parallel each for Nr reads. Submitting 1 job with M*Nr reads should to a good approximation produce the same result. It doesn't explain your BER gap.

@MAbuain17
Copy link
Author

also, when using CoMP (your demo) for higher modulation schemes (16QAM,64QAM,256QAM), i get this error
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) File [~\AppData\Roaming\Python\Python312\site-packages\dwave\embedding\transforms.py:261](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:261), in EmbeddedStructure.embed_bqm(self, source_bqm, chain_strength, smear_vartype) [260](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:260) try: --> [261](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:261) chain = self[v] [262](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:262) except KeyError: KeyError: 1920 During handling of the above exception, another exception occurred: MissingChainError Traceback (most recent call last) Cell In[79], line 3 1 sampler = FixedEmbeddingComposite(qpu, embedding) ----> 3 sampleset = sampler.sample(bqm, 4 num_reads=30, 5 annealing_time=200, 6 chain_strength=-0.13*min(bqm.linear.values()), 7 label='Notebook - Coordinated Multipoint') 9 _ = compare_signals(sampleset, transmitted_symbols) File [~\AppData\Roaming\Python\Python312\site-packages\dwave\system\composites\embedding.py:499](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/system/composites/embedding.py:499), in LazyFixedEmbeddingComposite.sample(self, bqm, **parameters) [494](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/system/composites/embedding.py:494) embedding = self.find_embedding(source_edgelist, target_edgelist, [495](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/system/composites/embedding.py:495) **embedding_parameters) [497](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/system/composites/embedding.py:497) self._fix_embedding(embedding) ... [266](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:266) if len(chain) == 1: [267](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:267) # in the case where the chain has length 1, there are no chain quadratic biases, [268](https://file+.vscode-resource.vscode-cdn.net/c%3A/path/to/myenv/Scripts/coordinated-multipoint-notebook/~/AppData/Roaming/Python/Python312/site-packages/dwave/embedding/transforms.py:268) # but we none-the-less want the chain variables to appear in the target_bqm MissingChainError: chain for 1920 is empty or not contained in this embedding Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
the issue also seems to be related to embedding, i tried changing it to clique but it gave error limit of 3xx something.. embedding composite seem to work ( takes alot of time ) but then it throws an error of mismatch in _compare_signals

The embedding is unfortunately specific both to the combination of the modulation scheme and the structure of network, it is BPSK only (as you found).

QPSK also works, and other modulation schemes require EmbeddingComposite but _ = compare_signals(sampleset, transmitted_symbols) is not working for QAM modulations.
i tried also to use your method of BER

To calculate the bit error rate, you can solve the bqm and then take your best solution (spins_ideal, a numpy array) and compare it to
'spins_ideal = dimod.generators.wireless._symbols_to_bits(transmitted_symbols, modulation=modulation)', which is the transmitted_symbols encoded as spins. I.e. Bit_error_rate = (1 - np.mean(spins_ideal*spins_best))/2. If and only if all the spins in the solution agree with the transmitted values this is zero.

but it also seems to be lacking something.. as QAM is symbols that have more than one bit embedded, how does QA output the spins in this case? from the paper you have as reference (by KIM) mentions mapping of symbols to qubo variables but i don't really understand it!
i also got confused by the function name _symbols_to_bits but i noticed that it's actually symbols_to_spins but you guys changed it!
if you care to explain/confirm _symbols_to_bits is indeed working properly for all modulations then maybe i can investigate it more!

@MAbuain17
Copy link
Author

MAbuain17 commented Apr 15, 2024

you are right, I have flipped the num# of Rx, Tx it should be the reverse. the weird thing is that if you notice the {len(bqm)} variables with {len(bqm.quadratic)} quadratic interactions. gives 'BQM has 1 variables with 0 quadratic interactions' which is not correct i think.. as for embedding you are right, but I thought that as I am using the same QUBO/ising model the fixed embedding will be the same. I have read in your documentation (Dwave website) EmbeddingComposite(qpu) that will automatically generate the appropriate embedding. I have given another shot using QPSK with 4 users with the above embedding:

`import numpy as np

for i, snr in enumerate(snr_db): print(f"SNR for User {i+1}: {snr:.2f} dB")`
the code seems to work but gives higher than expected (compared with results in the paper) BER hovering around ~0.25, i have tried to fiddle around with different SNR ( changing Power , pathloss distance , AWGN) but same results, how can i know if i am going on the right track?
also, I noticed the author of the paper mention something about running the same problem many times

The QA method was implemented on the proposed system model using D-Wave’s Advantage QPU [12]. It is important
to mention that the parallelization procedure was used to save the simulation time on the QA computer [3], i.e., 5 instances
of the problem were run at the same time on QPU. Since the 3-user BPSK problem requires only 3 logical qubits, 5 instances would occupy 15 logical qubits.

I know that the solution of QA will differ each run but is it critical to run the simulation many times( the author mentions 380times) and take the average to ensure accurateness?
sorry for the many questions but i don't have anyone else to talk to about it ! can't express my gratitude to your help 👍

I copy pasted some of this code to run, but there are missing dependencies. Regardless, I dont have much time to reproduce results. With 1 transmitter, in the 'Ising' Formulation, the quadratic term J is zero (and the field h is non-zero). Hence len(bqm.quadratic) == 0. In the QUBO formulation it would be 1, perhaps this is the source of the confusion. The two formulations are equivalent. I'm not sure why you are seeing 25% while the authors see smaller values. It is likely that the authors used a different chain strength for example (probably the default, I can't think of a reason 0.13 would be better than the default in this scenario). Aside from that difference, a careful reading of the paper is necessary to understand formulation differences; and if you continue to see a difference maybe contact the authors for reproducible code. They seem to be submitting multiple (M) jobs in parallel each for Nr reads. Submitting 1 job with M*Nr reads should to a good approximation produce the same result. It doesn't explain your BER gap.

can you elaborate on how to submit multiple (M) jobs in parallel at the same time? is it just simple loop that sequentially submit each time (not really parallel) or there's a specific command?

also for BER it seems that there's something associated with the array shape of BER method, that's why it's always giving 0.25 while it was giving 0

'spins_ideal = dimod.generators.wireless._symbols_to_bits(transmitted_symbols, modulation=modulation)', which is the transmitted_symbols encoded as spins. I.e. Bit_error_rate = (1 - np.mean(spins_ideal*spins_best))/2. If and only if all the spins in the solution agree with the transmitted values this is zero.

I have tried to fix it using

# Get the best solution
best_solution = sampleset.first.sample
# Convert the transmitted symbols to spins
spins_ideal = _symbols_to_bits(transmitted_symbols, modulation=modulation).flatten()

# Convert the best solution to a numpy array of spins
spins_best = np.array([best_solution[i] for i in range(len(best_solution))], dtype=int)

# Calculate the bit error rate
bit_error_rate = np.mean(spins_ideal != spins_best)

but now I get 0 errors! I mean literally everytime it decodes the bits correctly (too perfect as there must be some errors!) and the weird thing changing the channel coefficients in (F) or the number of users doesn't change the results, the only solution i can think of (not really a solution) is not to consider only best solution (first sample) but get many samples to account for BER.
I have read the paper many times, adjusted my code according to their specific conditions but no luck, i even tried to use their QUBO manually but no luck. using their QUBO seems waste of time as you mentioned your code (mimo) uses the same model the only difference is channel conditions
Unfortunately I have tried contacting the authors (along with couple more that have papers on the same topic) but none answered. I apologize for the many questions and I know you must be very busy and have little time, this is the only place that i could ask where people could actually understand!
I appreciate if you could take a look when you get time of course.
i will attach the codes as text file for your review , the code prints the transmitted and decoded symbols each time for debugging and manually inspecting them so we can assure BER is calculated correctly
NOMA BPSK (take many samples).txt
NOMA best sample only.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants