2525
2626mod_params = namedtuple ("mod_params" , ["bits_per_transmitter" ,
2727 "amplitudes" ,
28- "transmitters_per_spin " ,
28+ "transmitters_per_bit " ,
2929 "number_of_amps" ,
30- "spins_per_symbol " ])
30+ "bits_per_symbol " ])
3131mod_config = {
3232 "BPSK" : mod_params (1 , 1 , 1 , 1 , 1 ),
3333 "QPSK" : mod_params (2 , 1 , 2 , 1 , 1 ),
@@ -132,8 +132,8 @@ def _amplitude_modulated_quadratic_form(h, J, modulation="BPSK"):
132132 JA = np .kron (np .kron (amps [:, np .newaxis ], amps [np .newaxis , :]), J )
133133 return hA , JA
134134
135- def _symbols_to_spins (symbols , modulation = "BPSK" ):
136- """Convert quadrature amplitude modulated (QAM) symbols to spins .
135+ def _symbols_to_bits (symbols , modulation = "BPSK" ):
136+ """Convert quadrature amplitude modulated (QAM) symbols to bits .
137137
138138 Args:
139139 symbols: Transmitted symbols as a NumPy column vector.
@@ -143,7 +143,7 @@ def _symbols_to_spins(symbols, modulation="BPSK"):
143143 quadrature modulations 'QPSK', '16QAM', '64QAM', and '256QAM'.
144144
145145 Returns:
146- Spins as a NumPy array.
146+ Bits as a NumPy array.
147147 """
148148 if modulation not in mod_config :
149149 raise ValueError (f"Unsupported modulation: { modulation } " )
@@ -154,25 +154,25 @@ def _symbols_to_spins(symbols, modulation="BPSK"):
154154 if modulation == 'QPSK' :
155155 return np .concatenate ((symbols .real , symbols .imag ))
156156
157- spins_per_real_symbol = mod_config [modulation ].spins_per_symbol
157+ bits_per_real_symbol = mod_config [modulation ].bits_per_symbol
158158
159159 # A map from integer parts to real is clearest (and sufficiently performant),
160160 # generalizes to Gray coding more easily as well:
161161
162- symb_to_spins = {np .sum ([x * 2 ** xI for xI , x in enumerate (spins )]): spins
163- for spins in product (* spins_per_real_symbol * [(- 1 , 1 )])}
164- spins = np .concatenate (
165- [np .concatenate (([symb_to_spins [symb ][prec ] for symb in symbols .real .flatten ()],
166- [symb_to_spins [symb ][prec ] for symb in symbols .imag .flatten ()]))
167- for prec in range (spins_per_real_symbol )])
162+ symb_to_bits = {np .sum ([x * 2 ** xI for xI , x in enumerate (bits )]): bits
163+ for bits in product (* bits_per_real_symbol * [(- 1 , 1 )])}
164+ bits = np .concatenate (
165+ [np .concatenate (([symb_to_bits [symb ][prec ] for symb in symbols .real .flatten ()],
166+ [symb_to_bits [symb ][prec ] for symb in symbols .imag .flatten ()]))
167+ for prec in range (bits_per_real_symbol )])
168168
169169 if len (symbols .shape ) > 2 :
170170 raise ValueError (f"`symbols` should be 1 or 2 dimensional but is shape { symbols .shape } " )
171171
172172 if symbols .ndim == 1 : # If symbols shaped as vector, return as vector
173- spins .reshape ((len (spins ), ))
173+ bits .reshape ((len (bits ), ))
174174
175- return spins
175+ return bits
176176
177177def _yF_to_hJ (y , F , modulation = "BPSK" ):
178178 """Convert :math:`O(v) = ||y - F v||^2` to modulated quadratic form.
@@ -206,13 +206,13 @@ def _yF_to_hJ(y, F, modulation="BPSK"):
206206
207207 return h , J , offset
208208
209- def _spins_to_symbols ( spins ,
209+ def _bits_to_symbols ( bits ,
210210 modulation = "BPSK" ,
211211 num_transmitters = None ):
212- """Convert spins to modulated symbols.
212+ """Convert bits to modulated symbols.
213213
214214 Args:
215- spins: Spins as a NumPy array.
215+ bits: Bits as a NumPy array.
216216
217217 modulation: Modulation. Supported values are the default non-quadrature
218218 modulation, 'BPSK', and quadrature modulations 'QPSK', '16QAM',
@@ -224,28 +224,28 @@ def _spins_to_symbols(spins,
224224 if modulation not in mod_config :
225225 raise ValueError (f"Unsupported modulation: { modulation } " )
226226
227- num_spins = len (spins )
227+ num_bits = len (bits )
228228
229229 if num_transmitters is None :
230- num_transmitters = num_spins // mod_config [modulation ].transmitters_per_spin
230+ num_transmitters = num_bits // mod_config [modulation ].transmitters_per_bit
231231
232- if num_transmitters == num_spins :
233- symbols = spins
232+ if num_transmitters == num_bits :
233+ symbols = bits
234234 else :
235- num_amps , rem = divmod (len (spins ), (2 * num_transmitters ))
235+ num_amps , rem = divmod (len (bits ), (2 * num_transmitters ))
236236 if num_amps > 64 :
237237 raise ValueError ('Complex encoding is limited to 64 bits in'
238238 'real and imaginary parts; `num_transmitters` is'
239239 'too small' )
240240 if rem != 0 :
241- raise ValueError ('number of spins must be divisible by `num_transmitters` '
241+ raise ValueError ('number of bits must be divisible by `num_transmitters` '
242242 'for modulation schemes' )
243243
244- spinsR = np .reshape (spins , (num_amps , 2 * num_transmitters ))
244+ bitsR = np .reshape (bits , (num_amps , 2 * num_transmitters ))
245245 amps = 2 ** np .arange (0 , num_amps )[:, np .newaxis ]
246246
247- symbols = np .sum (amps * spinsR [:, :num_transmitters ], axis = 0 ) \
248- + 1j * np .sum (amps * spinsR [:, num_transmitters :], axis = 0 )
247+ symbols = np .sum (amps * bitsR [:, :num_transmitters ], axis = 0 ) \
248+ + 1j * np .sum (amps * bitsR [:, num_transmitters :], axis = 0 )
249249
250250 return symbols
251251
@@ -322,9 +322,6 @@ def create_channel(num_receivers: int = 1,
322322 attenuation_matrix : Optional [np .ndarray ] = None ) -> Tuple [np .ndarray , float ]:
323323 """Create a channel model.
324324
325- Channel power is the expected mean-square signal amplification per receiver (i.e.,
326- :math:`mean(F^2)*num_transmitters`) for homogeneous codes.
327-
328325 Args:
329326 num_receivers: Number of receivers.
330327
@@ -562,7 +559,7 @@ def mimo(modulation: Literal["BPSK", "QPSK", "16QAM", "64QAM", "256QAM"] = "BPSK
562559 subject to additive white Gaussian noise. Given the received signal,
563560 :math:`y`, the log likelihood of a given symbol set, :math:`v`, is
564561 :math:`MLE = argmin || y - F v ||_2`. When :math:`v` is encoded as
565- a linear sum of spins , the optimization problem is a binary quadratic model.
562+ a linear sum of bits , the optimization problem is a binary quadratic model.
566563
567564 Depending on its parameters, this function can model code division multiple
568565 access (CDMA) _[#T02, #R20], 5G communication networks _[#Prince], or
@@ -582,16 +579,16 @@ def mimo(modulation: Literal["BPSK", "QPSK", "16QAM", "64QAM", "256QAM"] = "BPSK
582579
583580 Quadrature Phase Shift Keying. Transmitted symbols are
584581 :math:`1+1j, 1-1j, -1+1j, -1-1j` normalized by
585- :math:`\\ frac{1}{\\ sqrt{2}}`. spins are encoded as a real vector
582+ :math:`\\ frac{1}{\\ sqrt{2}}`. Bits are encoded as a real vector
586583 concatenated with an imaginary vector.
587584
588585 * '16QAM'
589586
590587 Each user is assumed to select independently from 16 symbols.
591588 The transmitted symbol is a complex value that can be encoded
592- by two spins in the imaginary part and two spins in the real
593- part. Highest precision real and imaginary spin vectors are
594- concatenated to lower precision spin vectors.
589+ by two bits in the imaginary part and two bits in the real
590+ part. Highest precision real and imaginary bit vectors are
591+ concatenated to lower precision bit vectors.
595592
596593 * '64QAM'
597594
@@ -641,9 +638,9 @@ def mimo(modulation: Literal["BPSK", "QPSK", "16QAM", "64QAM", "256QAM"] = "BPSK
641638 respectively. Note that for correct analysis by some solvers, applying
642639 spin-reversal transforms may be necessary.
643640
644- For QAM modulations, amplitude randomness affects likelihood in a
645- non-trivial way. By default, symbols are chosen independently and
646- identically distributed from the constellations.
641+ For QAM modulations such as 16QAM , amplitude randomness affects
642+ likelihood in a non-trivial way. By default, symbols are chosen
643+ independently and identically distributed from the constellations.
647644
648645 channel_noise: Channel noise as a NumPy array of complex values. Must
649646 be consistent with the number of receivers.
@@ -767,7 +764,7 @@ def coordinated_multipoint(lattice: 'networkx.Graph',
767764 subject to additive white Gaussian noise. Given the received signal,
768765 :math:`y`, the log likelihood of a given symbol set, :math:`v`, is
769766 :math:`MLE = argmin || y - F v ||_2`. When :math:`v` is encoded as
770- a linear sum of spins , the optimization problem is a binary quadratic model.
767+ a linear sum of bits , the optimization problem is a binary quadratic model.
771768
772769 Args:
773770 lattice: Geometry, as a :class:`networkx.Graph`, defining
@@ -788,14 +785,14 @@ def coordinated_multipoint(lattice: 'networkx.Graph',
788785 * 'QPSK'
789786 Quadrature Phase Shift Keying. Transmitted symbols are
790787 :math:`1+1j, 1-1j, -1+1j, -1-1j` normalized by
791- :math:`\\ frac{1}{\\ sqrt{2}}`. Spins are encoded as a real vector
788+ :math:`\\ frac{1}{\\ sqrt{2}}`. Bits are encoded as a real vector
792789 concatenated with an imaginary vector.
793790 * '16QAM'
794791 Each user is assumed to select independently from 16 symbols.
795792 The transmitted symbol is a complex value that can be encoded
796- by two spins in the imaginary part and two spins in the real
797- part. Highest precision real and imaginary spin vectors are
798- concatenated to lower precision spin vectors.
793+ by two bits in the imaginary part and two bits in the real
794+ part. Highest precision real and imaginary bit vectors are
795+ concatenated to lower precision bit vectors.
799796 * '64QAM'
800797 A QPSK symbol set is generated and symbols are further amplitude
801798 modulated by an independently and uniformly distributed random
@@ -820,9 +817,9 @@ def coordinated_multipoint(lattice: 'networkx.Graph',
820817 respectively. Note that for correct analysis by some solvers,
821818 applying spin-reversal transforms may be necessary.
822819
823- For QAM modulations, amplitude randomness affects likelihood in a
824- non-trivial way. By default, symbols are chosen independently and
825- identically distributed from the constellations.
820+ For QAM modulations such as 16QAM , amplitude randomness affects
821+ likelihood in a non-trivial way. By default, symbols are chosen
822+ independently and identically distributed from the constellations.
826823
827824 channel_noise: Channel noise as a complex value.
828825
@@ -896,7 +893,7 @@ def coordinated_multipoint(lattice: 'networkx.Graph',
896893
897894 return bqm
898895
899- # Linear-filter functions. These are not used for spin -encoding MIMO problems
896+ # Linear-filter functions. These are not used for bit -encoding MIMO problems
900897# and are maintained here for user convenience
901898
902899def linear_filter (F , method = 'zero_forcing' , SNRoverNt = float ('Inf' ), PoverNt = 1 ):
0 commit comments