vlcSim 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vlcSim-0.3.2 → vlcSim-0.3.4}/PKG-INFO +1 -1
- {vlcSim-0.3.2 → vlcSim-0.3.4}/setup.py +1 -1
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcSim.egg-info/PKG-INFO +1 -1
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcsim/controller.py +100 -2
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcsim/scene.py +371 -30
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcsim/simulator.py +190 -40
- {vlcSim-0.3.2 → vlcSim-0.3.4}/LICENSE.md +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/README.md +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/setup.cfg +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/test/test_receiver.py +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/test/test_scenario.py +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/test/test_vled.py +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcSim.egg-info/SOURCES.txt +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcSim.egg-info/dependency_links.txt +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcSim.egg-info/not-zip-safe +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcSim.egg-info/requires.txt +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcSim.egg-info/top_level.txt +0 -0
- {vlcSim-0.3.2 → vlcSim-0.3.4}/vlcsim/__init__.py +0 -0
|
@@ -10,7 +10,7 @@ long_description = (this_directory / "README.md").read_text()
|
|
|
10
10
|
|
|
11
11
|
setup(
|
|
12
12
|
name="vlcSim",
|
|
13
|
-
version="0.3.
|
|
13
|
+
version="0.3.4",
|
|
14
14
|
license="MIT",
|
|
15
15
|
description="Python Package of Event-Oriented Simulation for visible light communication",
|
|
16
16
|
author="Danilo Bórquez-Paredes",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
The :mod:`vlcsim.controller` module is in charge of managing the connections and the physical sustrate.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
from .scene import *
|
|
6
7
|
from enum import Enum
|
|
7
8
|
import math
|
|
@@ -321,8 +322,7 @@ class Controller:
|
|
|
321
322
|
if self.__allocationStatus == Controller.status.ALLOCATED:
|
|
322
323
|
index = self.APPosition(connection.AP)
|
|
323
324
|
self.__numberActiveConnections[index] += 1
|
|
324
|
-
actualSlice = connection.nextSliceInAPWhenArriving(
|
|
325
|
-
connection.AP) - 1
|
|
325
|
+
actualSlice = connection.nextSliceInAPWhenArriving(connection.AP) - 1
|
|
326
326
|
actualTime = (
|
|
327
327
|
(time // (connection.AP.slicesInFrame * connection.AP.sliceTime))
|
|
328
328
|
* connection.AP.slicesInFrame
|
|
@@ -535,3 +535,101 @@ class Controller:
|
|
|
535
535
|
:return: A list of lists containing the frames and slices of this AP
|
|
536
536
|
"""
|
|
537
537
|
return self.__activeConnections[self.APPosition(ap)]
|
|
538
|
+
|
|
539
|
+
def default_alloc(
|
|
540
|
+
receiver, connection: Connection, scenario: Scenario, controller: Controller
|
|
541
|
+
):
|
|
542
|
+
vleds = scenario.vleds
|
|
543
|
+
rfs = scenario.rfs
|
|
544
|
+
vled_snr = []
|
|
545
|
+
rf_snr = []
|
|
546
|
+
for vled in vleds:
|
|
547
|
+
vled_snr.append(scenario.snrVled(receiver, vled))
|
|
548
|
+
for rf in rfs:
|
|
549
|
+
rf_snr.append(scenario.snrRf(receiver, rf))
|
|
550
|
+
|
|
551
|
+
numberOfSlices = 0
|
|
552
|
+
for vled_pos in range(len(vleds)):
|
|
553
|
+
number_better_rf = 0
|
|
554
|
+
for rf_pos in range(len(rfs)):
|
|
555
|
+
if vled_snr[vled_pos] > rf_snr[rf_pos]:
|
|
556
|
+
if controller.numberOfActiveConnections(vleds[vled_pos]) < 5:
|
|
557
|
+
connection.AP = vleds[vled_pos]
|
|
558
|
+
connection.receiver.capacityFromAP = scenario.capacityVled(
|
|
559
|
+
receiver, connection.AP
|
|
560
|
+
)
|
|
561
|
+
numberOfSlices = connection.numberOfSlicesNeeded(
|
|
562
|
+
connection.capacityRequired,
|
|
563
|
+
connection.receiver.capacityFromAP,
|
|
564
|
+
)
|
|
565
|
+
connection.snr = vled_snr[vled_pos]
|
|
566
|
+
if numberOfSlices < 5:
|
|
567
|
+
number_better_rf += 1
|
|
568
|
+
break
|
|
569
|
+
else:
|
|
570
|
+
number_better_rf += 1
|
|
571
|
+
break
|
|
572
|
+
else:
|
|
573
|
+
number_better_rf += 1
|
|
574
|
+
break
|
|
575
|
+
if number_better_rf == 0:
|
|
576
|
+
break
|
|
577
|
+
if number_better_rf != 0:
|
|
578
|
+
best_rf_SNR = sys.float_info.min
|
|
579
|
+
best_rf = None
|
|
580
|
+
for rf_pos in range(len(rfs)):
|
|
581
|
+
if rf_snr[rf_pos] > best_rf_SNR:
|
|
582
|
+
best_rf_SNR = rf_snr[rf_pos]
|
|
583
|
+
best_rf = rf_pos
|
|
584
|
+
connection.AP = rfs[best_rf]
|
|
585
|
+
connection.receiver.capacityFromAP = scenario.capacityRf(
|
|
586
|
+
receiver, connection.AP
|
|
587
|
+
)
|
|
588
|
+
numberOfSlices = connection.numberOfSlicesNeeded(
|
|
589
|
+
connection.capacityRequired, connection.receiver.capacityFromAP
|
|
590
|
+
)
|
|
591
|
+
connection.snr = rf_snr[rf_pos]
|
|
592
|
+
else:
|
|
593
|
+
for vled_pos in range(len(vleds)):
|
|
594
|
+
if vled_snr[vled_pos] > connection.snr:
|
|
595
|
+
connection.AP = vleds[vled_pos]
|
|
596
|
+
connection.receiver.capacityFromAP = scenario.capacityVled(
|
|
597
|
+
receiver, connection.AP
|
|
598
|
+
)
|
|
599
|
+
numberOfSlices = connection.numberOfSlicesNeeded(
|
|
600
|
+
connection.capacityRequired, connection.receiver.capacityFromAP
|
|
601
|
+
)
|
|
602
|
+
connection.snr = vled_snr[vled_pos]
|
|
603
|
+
|
|
604
|
+
actualSlice = connection.nextSliceInAPWhenArriving(connection.AP)
|
|
605
|
+
aux = 0
|
|
606
|
+
auxFrame = 0
|
|
607
|
+
|
|
608
|
+
# Actual frame
|
|
609
|
+
for slice in range(actualSlice, connection.AP.slicesInFrame):
|
|
610
|
+
if (
|
|
611
|
+
len(controller.framesState(connection.AP)) == 0
|
|
612
|
+
or controller.framesState(connection.AP)[0][slice] == False
|
|
613
|
+
):
|
|
614
|
+
connection.assignFrameSlice(0, slice)
|
|
615
|
+
aux += 1
|
|
616
|
+
break
|
|
617
|
+
|
|
618
|
+
# next frames
|
|
619
|
+
for frameIndex in range(1, len(controller.framesState(connection.AP))):
|
|
620
|
+
for slice in range(connection.AP.slicesInFrame):
|
|
621
|
+
if controller.framesState(connection.AP)[frameIndex][slice] == False:
|
|
622
|
+
connection.assignFrameSlice(frameIndex, slice)
|
|
623
|
+
aux += 1
|
|
624
|
+
auxFrame = frameIndex
|
|
625
|
+
break
|
|
626
|
+
|
|
627
|
+
if aux == numberOfSlices:
|
|
628
|
+
break
|
|
629
|
+
|
|
630
|
+
frameIndex = auxFrame + 1
|
|
631
|
+
while aux < numberOfSlices:
|
|
632
|
+
connection.assignFrameSlice(frameIndex, 0)
|
|
633
|
+
frameIndex += 1
|
|
634
|
+
aux += 1
|
|
635
|
+
return Controller.status.ALLOCATED, connection
|
|
@@ -467,6 +467,17 @@ class RF(AccessPoint):
|
|
|
467
467
|
|
|
468
468
|
@property
|
|
469
469
|
def pif(self) -> float:
|
|
470
|
+
"""
|
|
471
|
+
The received SNR discrepancy from the continuous input memoryless channel’s capacity at the target BER. (pif=-1.5log2-1(5 BERf))
|
|
472
|
+
|
|
473
|
+
.. math::
|
|
474
|
+
\\begin{eqnarray}
|
|
475
|
+
pif = -1.5 \log_2^{-1}(5\cdot BERf)
|
|
476
|
+
\\end{eqnarray}
|
|
477
|
+
|
|
478
|
+
:return: SNR discrepancy
|
|
479
|
+
:rtype: float
|
|
480
|
+
"""
|
|
470
481
|
return self.__pif
|
|
471
482
|
|
|
472
483
|
@pif.setter
|
|
@@ -489,6 +500,12 @@ class RF(AccessPoint):
|
|
|
489
500
|
|
|
490
501
|
@property
|
|
491
502
|
def nFactor_rf(self) -> float:
|
|
503
|
+
"""
|
|
504
|
+
RF constant
|
|
505
|
+
|
|
506
|
+
:return: RF constant
|
|
507
|
+
:rtype: float
|
|
508
|
+
"""
|
|
492
509
|
return self.__nFactor_rf
|
|
493
510
|
|
|
494
511
|
@nFactor_rf.setter
|
|
@@ -497,6 +514,12 @@ class RF(AccessPoint):
|
|
|
497
514
|
|
|
498
515
|
@property
|
|
499
516
|
def A(self) -> float:
|
|
517
|
+
"""
|
|
518
|
+
Rayleigh distributed channel gain.
|
|
519
|
+
|
|
520
|
+
:return: Rayleigh distributed channel gain.
|
|
521
|
+
:rtype: float
|
|
522
|
+
"""
|
|
500
523
|
return self.__A
|
|
501
524
|
|
|
502
525
|
@A.setter
|
|
@@ -505,7 +528,14 @@ class RF(AccessPoint):
|
|
|
505
528
|
|
|
506
529
|
|
|
507
530
|
class Receiver:
|
|
531
|
+
"""
|
|
532
|
+
Class that represents a VLC object
|
|
533
|
+
"""
|
|
534
|
+
|
|
508
535
|
receiversCreated = 0
|
|
536
|
+
"""
|
|
537
|
+
Number of receivers created by this class.
|
|
538
|
+
"""
|
|
509
539
|
|
|
510
540
|
def __init__(
|
|
511
541
|
self,
|
|
@@ -549,7 +579,7 @@ class Receiver:
|
|
|
549
579
|
:type fov: float
|
|
550
580
|
:param q: electronic load. Default is -1.602e-19 culombios
|
|
551
581
|
:type q: float
|
|
552
|
-
:param s: ibg b - parameter of the Ib - Galactic model. Default
|
|
582
|
+
:param s: ibg b - parameter of the Ib - Galactic model. Default is 5 seconds.
|
|
553
583
|
:type s: float
|
|
554
584
|
:param b: c b - parameter of the Ib - Galactic model. Default is 5 seconds.
|
|
555
585
|
:type b: float
|
|
@@ -678,6 +708,12 @@ class Receiver:
|
|
|
678
708
|
|
|
679
709
|
@property
|
|
680
710
|
def aDet(self) -> float:
|
|
711
|
+
"""
|
|
712
|
+
aDet value of the object's coordinate.
|
|
713
|
+
|
|
714
|
+
:return: aDet value of the object's coordinate.
|
|
715
|
+
:rtype: float
|
|
716
|
+
"""
|
|
681
717
|
return self.__aDet
|
|
682
718
|
|
|
683
719
|
@aDet.setter
|
|
@@ -686,6 +722,12 @@ class Receiver:
|
|
|
686
722
|
|
|
687
723
|
@property
|
|
688
724
|
def ts(self) -> float:
|
|
725
|
+
"""
|
|
726
|
+
time of the object's coordinate. Default is 10 seconds.
|
|
727
|
+
|
|
728
|
+
:return: time of the object's coordinate.
|
|
729
|
+
:rtype: float
|
|
730
|
+
"""
|
|
689
731
|
return self.__ts
|
|
690
732
|
|
|
691
733
|
@ts.setter
|
|
@@ -694,6 +736,12 @@ class Receiver:
|
|
|
694
736
|
|
|
695
737
|
@property
|
|
696
738
|
def index(self) -> float:
|
|
739
|
+
"""
|
|
740
|
+
order of Lambertian emission that depends on the half-angle at half illumination of the LED.
|
|
741
|
+
|
|
742
|
+
:return: order of Lambertian emission
|
|
743
|
+
:rtype: float
|
|
744
|
+
"""
|
|
697
745
|
return self.__index
|
|
698
746
|
|
|
699
747
|
@index.setter
|
|
@@ -702,6 +750,12 @@ class Receiver:
|
|
|
702
750
|
|
|
703
751
|
@property
|
|
704
752
|
def fov(self) -> float:
|
|
753
|
+
"""
|
|
754
|
+
width of the field of view.
|
|
755
|
+
|
|
756
|
+
:return: width of the field of view.
|
|
757
|
+
:rtype: float
|
|
758
|
+
"""
|
|
705
759
|
return self.__fov
|
|
706
760
|
|
|
707
761
|
@fov.setter
|
|
@@ -713,7 +767,7 @@ class Receiver:
|
|
|
713
767
|
return self.__gCon
|
|
714
768
|
|
|
715
769
|
@property
|
|
716
|
-
def position(self):
|
|
770
|
+
def position(self) -> float:
|
|
717
771
|
"""
|
|
718
772
|
Return the position of the object. This is a tuple of ( x y z)
|
|
719
773
|
|
|
@@ -724,6 +778,12 @@ class Receiver:
|
|
|
724
778
|
|
|
725
779
|
@property
|
|
726
780
|
def q(self):
|
|
781
|
+
"""
|
|
782
|
+
electronic load. Default is -1.602e-19 culombios
|
|
783
|
+
|
|
784
|
+
:return: electronic load.
|
|
785
|
+
:rtype: _type_
|
|
786
|
+
"""
|
|
727
787
|
return self.__q
|
|
728
788
|
|
|
729
789
|
@q.setter
|
|
@@ -732,6 +792,11 @@ class Receiver:
|
|
|
732
792
|
|
|
733
793
|
@property
|
|
734
794
|
def s(self):
|
|
795
|
+
"""
|
|
796
|
+
ibg b - parameter of the Ib - Galactic model. Default is 5 seconds.
|
|
797
|
+
|
|
798
|
+
:return: ibg b - parameter of the Ib - Galactic model.
|
|
799
|
+
"""
|
|
735
800
|
return self.__s
|
|
736
801
|
|
|
737
802
|
@s.setter
|
|
@@ -740,6 +805,11 @@ class Receiver:
|
|
|
740
805
|
|
|
741
806
|
@property
|
|
742
807
|
def b(self):
|
|
808
|
+
"""
|
|
809
|
+
c b - parameter of the Ib - Galactic model.
|
|
810
|
+
|
|
811
|
+
:return: c b - parameter of the Ib - Galactic model.
|
|
812
|
+
"""
|
|
743
813
|
return self.__b
|
|
744
814
|
|
|
745
815
|
@b.setter
|
|
@@ -747,7 +817,13 @@ class Receiver:
|
|
|
747
817
|
self.__b = value
|
|
748
818
|
|
|
749
819
|
@property
|
|
750
|
-
def ibg(self):
|
|
820
|
+
def ibg(self) -> float:
|
|
821
|
+
"""
|
|
822
|
+
background current. Default is 5.1e-3 Amperes.
|
|
823
|
+
|
|
824
|
+
:return: background current.
|
|
825
|
+
:rtype: float
|
|
826
|
+
"""
|
|
751
827
|
return self.__ibg
|
|
752
828
|
|
|
753
829
|
@ibg.setter
|
|
@@ -755,7 +831,13 @@ class Receiver:
|
|
|
755
831
|
self.__ibg = value
|
|
756
832
|
|
|
757
833
|
@property
|
|
758
|
-
def cb(self):
|
|
834
|
+
def cb(self) -> float:
|
|
835
|
+
"""
|
|
836
|
+
Boltzmann constant. Default is 1.380649e-23 J/K.
|
|
837
|
+
|
|
838
|
+
:return: Boltzmann constant.
|
|
839
|
+
:rtype: float
|
|
840
|
+
"""
|
|
759
841
|
return self.__cb
|
|
760
842
|
|
|
761
843
|
@cb.setter
|
|
@@ -763,7 +845,7 @@ class Receiver:
|
|
|
763
845
|
self.__cb = value
|
|
764
846
|
|
|
765
847
|
@property
|
|
766
|
-
def tk(self):
|
|
848
|
+
def tk(self) -> float:
|
|
767
849
|
return self.__tk
|
|
768
850
|
|
|
769
851
|
@tk.setter
|
|
@@ -771,7 +853,13 @@ class Receiver:
|
|
|
771
853
|
self.__tk = value
|
|
772
854
|
|
|
773
855
|
@property
|
|
774
|
-
def a(self):
|
|
856
|
+
def a(self) -> float:
|
|
857
|
+
"""
|
|
858
|
+
n n - parameter of the B - parameter. Default is 10 seconds.
|
|
859
|
+
|
|
860
|
+
:return: n n - B - parameter
|
|
861
|
+
:rtype: float
|
|
862
|
+
"""
|
|
775
863
|
return self.__a
|
|
776
864
|
|
|
777
865
|
@a.setter
|
|
@@ -779,7 +867,13 @@ class Receiver:
|
|
|
779
867
|
self.__a = value
|
|
780
868
|
|
|
781
869
|
@property
|
|
782
|
-
def gv(self):
|
|
870
|
+
def gv(self) -> float:
|
|
871
|
+
"""
|
|
872
|
+
Open-loop voltage gain. Default is 10
|
|
873
|
+
|
|
874
|
+
:return: Open-loop voltage gain.
|
|
875
|
+
:rtype: float
|
|
876
|
+
"""
|
|
783
877
|
return self.__gv
|
|
784
878
|
|
|
785
879
|
@gv.setter
|
|
@@ -787,7 +881,13 @@ class Receiver:
|
|
|
787
881
|
self.__gv = value
|
|
788
882
|
|
|
789
883
|
@property
|
|
790
|
-
def n(self):
|
|
884
|
+
def n(self) -> float:
|
|
885
|
+
"""
|
|
886
|
+
Fixed capacitance of the PD per unit area. Default is 1.12e-6.
|
|
887
|
+
|
|
888
|
+
:return: Fixed capacitance of the PD per unit area.
|
|
889
|
+
:rtype: float
|
|
890
|
+
"""
|
|
791
891
|
return self.__n
|
|
792
892
|
|
|
793
893
|
@n.setter
|
|
@@ -795,7 +895,13 @@ class Receiver:
|
|
|
795
895
|
self.__n = value
|
|
796
896
|
|
|
797
897
|
@property
|
|
798
|
-
def fr(self):
|
|
898
|
+
def fr(self) -> float:
|
|
899
|
+
"""
|
|
900
|
+
FET channel noise factor. Default is 1.5
|
|
901
|
+
|
|
902
|
+
:return: FET channel noise factor.
|
|
903
|
+
:rtype: float
|
|
904
|
+
"""
|
|
799
905
|
return self.__fr
|
|
800
906
|
|
|
801
907
|
@fr.setter
|
|
@@ -803,7 +909,13 @@ class Receiver:
|
|
|
803
909
|
self.__fr = value
|
|
804
910
|
|
|
805
911
|
@property
|
|
806
|
-
def gm(self):
|
|
912
|
+
def gm(self) -> float:
|
|
913
|
+
"""
|
|
914
|
+
FET transconductance. Default is 3e-2.
|
|
915
|
+
|
|
916
|
+
:return: FET transconductance.
|
|
917
|
+
:rtype: float
|
|
918
|
+
"""
|
|
807
919
|
return self.__gm
|
|
808
920
|
|
|
809
921
|
@gm.setter
|
|
@@ -811,7 +923,13 @@ class Receiver:
|
|
|
811
923
|
self.__gm = value
|
|
812
924
|
|
|
813
925
|
@property
|
|
814
|
-
def i1(self):
|
|
926
|
+
def i1(self) -> float:
|
|
927
|
+
"""
|
|
928
|
+
constant experimental value. Default is 0.562.
|
|
929
|
+
|
|
930
|
+
:return: constant experimental value.
|
|
931
|
+
:rtype: float
|
|
932
|
+
"""
|
|
815
933
|
return self.__i1
|
|
816
934
|
|
|
817
935
|
@i1.setter
|
|
@@ -819,7 +937,13 @@ class Receiver:
|
|
|
819
937
|
self.__i1 = value
|
|
820
938
|
|
|
821
939
|
@property
|
|
822
|
-
def i2(self):
|
|
940
|
+
def i2(self) -> float:
|
|
941
|
+
"""
|
|
942
|
+
constant experimental value. Default is 0.0868.
|
|
943
|
+
|
|
944
|
+
:return: constant experimental value.
|
|
945
|
+
:rtype: float
|
|
946
|
+
"""
|
|
823
947
|
return self.__i2
|
|
824
948
|
|
|
825
949
|
@i2.setter
|
|
@@ -827,7 +951,13 @@ class Receiver:
|
|
|
827
951
|
self.__i2 = value
|
|
828
952
|
|
|
829
953
|
@property
|
|
830
|
-
def timeFirstConnected(self):
|
|
954
|
+
def timeFirstConnected(self) -> float:
|
|
955
|
+
"""
|
|
956
|
+
time point at which this receiver was first connected
|
|
957
|
+
|
|
958
|
+
:return: time point at which this receiver was first connected
|
|
959
|
+
:rtype: float
|
|
960
|
+
"""
|
|
831
961
|
return self.__timeFirstConnected
|
|
832
962
|
|
|
833
963
|
@timeFirstConnected.setter
|
|
@@ -835,7 +965,13 @@ class Receiver:
|
|
|
835
965
|
self.__timeFirstConnected = value
|
|
836
966
|
|
|
837
967
|
@property
|
|
838
|
-
def goalTime(self):
|
|
968
|
+
def goalTime(self) -> float:
|
|
969
|
+
"""
|
|
970
|
+
Amount of time that this receiver will be connected. Depends on tha SNR.
|
|
971
|
+
|
|
972
|
+
:return: Amount of time that this receiver will be connected.
|
|
973
|
+
:rtype: float
|
|
974
|
+
"""
|
|
839
975
|
return self.__goalTime
|
|
840
976
|
|
|
841
977
|
@goalTime.setter
|
|
@@ -843,7 +979,13 @@ class Receiver:
|
|
|
843
979
|
self.__goalTime = value
|
|
844
980
|
|
|
845
981
|
@property
|
|
846
|
-
def timeActive(self):
|
|
982
|
+
def timeActive(self) -> float:
|
|
983
|
+
"""
|
|
984
|
+
Effective time connected.
|
|
985
|
+
|
|
986
|
+
:return: Effective time connected
|
|
987
|
+
:rtype: float
|
|
988
|
+
"""
|
|
847
989
|
return self.__timeActive
|
|
848
990
|
|
|
849
991
|
@timeActive.setter
|
|
@@ -851,7 +993,13 @@ class Receiver:
|
|
|
851
993
|
self.__timeActive = value
|
|
852
994
|
|
|
853
995
|
@property
|
|
854
|
-
def timeFinished(self):
|
|
996
|
+
def timeFinished(self) -> float:
|
|
997
|
+
"""
|
|
998
|
+
point in time when this receiver wil be finished.
|
|
999
|
+
|
|
1000
|
+
:return: point in time when this receiver wil be finished.
|
|
1001
|
+
:rtype: float
|
|
1002
|
+
"""
|
|
855
1003
|
return self.__timeFinished
|
|
856
1004
|
|
|
857
1005
|
@timeFinished.setter
|
|
@@ -860,7 +1008,21 @@ class Receiver:
|
|
|
860
1008
|
|
|
861
1009
|
|
|
862
1010
|
class Scenario:
|
|
1011
|
+
"""
|
|
1012
|
+
Class that represents the characteristics of the scenario
|
|
1013
|
+
|
|
1014
|
+
:return: _description_
|
|
1015
|
+
:rtype: _type_
|
|
1016
|
+
"""
|
|
1017
|
+
|
|
863
1018
|
numberOfAPs = 0
|
|
1019
|
+
"""
|
|
1020
|
+
Number of access points in the scenario.
|
|
1021
|
+
|
|
1022
|
+
:return: Number of access points in the scenario.
|
|
1023
|
+
:rtype: int
|
|
1024
|
+
"""
|
|
1025
|
+
|
|
864
1026
|
warnings.filterwarnings(
|
|
865
1027
|
"ignore", message="invalid value encountered in double_scalars"
|
|
866
1028
|
)
|
|
@@ -868,6 +1030,19 @@ class Scenario:
|
|
|
868
1030
|
def __init__(
|
|
869
1031
|
self, width: float, length: float, height: float, nGrids: int, rho: float
|
|
870
1032
|
) -> None:
|
|
1033
|
+
"""Scenario Constructor
|
|
1034
|
+
|
|
1035
|
+
:param width: Width of the room
|
|
1036
|
+
:type width: float
|
|
1037
|
+
:param length: Length of the room
|
|
1038
|
+
:type length: float
|
|
1039
|
+
:param height: Height of the room
|
|
1040
|
+
:type height: float
|
|
1041
|
+
:param nGrids: Number of grids of each VLED
|
|
1042
|
+
:type nGrids: int
|
|
1043
|
+
:param rho: Reflexion coefficient
|
|
1044
|
+
:type rho: float
|
|
1045
|
+
"""
|
|
871
1046
|
self.__length = length # x
|
|
872
1047
|
self.__width = width # y
|
|
873
1048
|
self.__height = height # z
|
|
@@ -897,16 +1072,38 @@ class Scenario:
|
|
|
897
1072
|
self.__g_xyz = np.array([self.__g_x, self.__g_y, self.__g_z], dtype=object)
|
|
898
1073
|
|
|
899
1074
|
def addVLed(self, vled: VLed):
|
|
1075
|
+
"""
|
|
1076
|
+
Add a VLED to this Scenario
|
|
1077
|
+
|
|
1078
|
+
:param vled: the VLED to be added
|
|
1079
|
+
:type vled: VLed
|
|
1080
|
+
"""
|
|
900
1081
|
self.__vleds.append(vled)
|
|
901
1082
|
self.__vledsPositions.append(Scenario.numberOfAPs)
|
|
902
1083
|
Scenario.numberOfAPs += 1
|
|
903
1084
|
|
|
904
1085
|
def addRF(self, rf: RF):
|
|
1086
|
+
"""
|
|
1087
|
+
Add an RF to this Scenario
|
|
1088
|
+
|
|
1089
|
+
:param rf: The RF to be added
|
|
1090
|
+
:type rf: RF
|
|
1091
|
+
"""
|
|
905
1092
|
self.__femtocells.append(rf)
|
|
906
1093
|
self.__rfsPositions.append(Scenario.numberOfAPs)
|
|
907
1094
|
Scenario.numberOfAPs += 1
|
|
908
1095
|
|
|
909
1096
|
def getPowerInPointFromWalls(self, receiver: Receiver, vledID: int) -> float:
|
|
1097
|
+
"""
|
|
1098
|
+
Get the incident power in an specific point in the room, received from the walls.
|
|
1099
|
+
|
|
1100
|
+
:param receiver: The receiver which is in the point
|
|
1101
|
+
:type receiver: Receiver
|
|
1102
|
+
:param vledID: The VLED that is sending the signal
|
|
1103
|
+
:type vledID: int
|
|
1104
|
+
:return: Power from walls
|
|
1105
|
+
:rtype: float
|
|
1106
|
+
"""
|
|
910
1107
|
vled = self.__vleds[vledID]
|
|
911
1108
|
h1 = self.__channelGainWall(receiver, vled, 1, 0)
|
|
912
1109
|
h2 = self.__channelGainWall(receiver, vled, 0, 1)
|
|
@@ -916,6 +1113,16 @@ class Scenario:
|
|
|
916
1113
|
return float(power)
|
|
917
1114
|
|
|
918
1115
|
def getPowerInPointFromVled(self, receiver: Receiver, vledID: int) -> float:
|
|
1116
|
+
"""
|
|
1117
|
+
Get the power from the VLED in LOS
|
|
1118
|
+
|
|
1119
|
+
:param receiver: The receiver which is in the point
|
|
1120
|
+
:type receiver: Receiver
|
|
1121
|
+
:param vledID: The VLED that is sending the signal
|
|
1122
|
+
:type vledID: int
|
|
1123
|
+
:return: Power from VLED
|
|
1124
|
+
:rtype: float
|
|
1125
|
+
"""
|
|
919
1126
|
vled = self.__vleds[vledID]
|
|
920
1127
|
D_los = m.sqrt(
|
|
921
1128
|
(receiver.x - vled.x) ** 2
|
|
@@ -940,7 +1147,23 @@ class Scenario:
|
|
|
940
1147
|
)
|
|
941
1148
|
return power
|
|
942
1149
|
|
|
943
|
-
def __channelGainWall(
|
|
1150
|
+
def __channelGainWall(
|
|
1151
|
+
self, receiver: Receiver, vled: VLed, posVar: int, posFixed: int
|
|
1152
|
+
) -> float:
|
|
1153
|
+
"""
|
|
1154
|
+
Gain in channel from walls
|
|
1155
|
+
|
|
1156
|
+
:param receiver: The receiver which is in the point
|
|
1157
|
+
:type receiver: Receiver
|
|
1158
|
+
:param vled: The VLED that is sending the signal
|
|
1159
|
+
:type vled: VLed
|
|
1160
|
+
:param posVar: Auxiliar variable
|
|
1161
|
+
:type posVar: int
|
|
1162
|
+
:param posFixed: Auxiliar variable
|
|
1163
|
+
:type posFixed: int
|
|
1164
|
+
:return: Gain in channel
|
|
1165
|
+
:rtype: float
|
|
1166
|
+
"""
|
|
944
1167
|
wall = None
|
|
945
1168
|
dA = self.__height
|
|
946
1169
|
if posFixed == 0:
|
|
@@ -978,23 +1201,53 @@ class Scenario:
|
|
|
978
1201
|
return h
|
|
979
1202
|
|
|
980
1203
|
@property
|
|
981
|
-
def numberOfVLeds(self):
|
|
1204
|
+
def numberOfVLeds(self) -> int:
|
|
1205
|
+
"""
|
|
1206
|
+
number of VLeds in this scenario
|
|
1207
|
+
|
|
1208
|
+
:return: number of vleds
|
|
1209
|
+
:rtype: int
|
|
1210
|
+
"""
|
|
982
1211
|
return len(self.__vleds)
|
|
983
1212
|
|
|
984
1213
|
@property
|
|
985
|
-
def numberOfRFs(self):
|
|
1214
|
+
def numberOfRFs(self) -> int:
|
|
1215
|
+
"""
|
|
1216
|
+
Number of RFs in this scenario
|
|
1217
|
+
|
|
1218
|
+
:return: number of RFs
|
|
1219
|
+
:rtype: int
|
|
1220
|
+
"""
|
|
986
1221
|
return len(self.__femtocells)
|
|
987
1222
|
|
|
988
1223
|
@property
|
|
989
|
-
def vleds(self):
|
|
1224
|
+
def vleds(self) -> list:
|
|
1225
|
+
"""
|
|
1226
|
+
set of VLEDs in this scenario.
|
|
1227
|
+
|
|
1228
|
+
:return: set of VLEDs
|
|
1229
|
+
:rtype: list
|
|
1230
|
+
"""
|
|
990
1231
|
return self.__vleds
|
|
991
1232
|
|
|
992
1233
|
@property
|
|
993
|
-
def rfs(self):
|
|
1234
|
+
def rfs(self) -> list:
|
|
1235
|
+
"""
|
|
1236
|
+
List of RFs in this scenario
|
|
1237
|
+
|
|
1238
|
+
:return: List of RFs
|
|
1239
|
+
:rtype: list
|
|
1240
|
+
"""
|
|
994
1241
|
return self.__femtocells
|
|
995
1242
|
|
|
996
1243
|
@property
|
|
997
|
-
def start_x(self):
|
|
1244
|
+
def start_x(self) -> float:
|
|
1245
|
+
"""
|
|
1246
|
+
Auxiliar variable determining the starting X coordinate of the room
|
|
1247
|
+
|
|
1248
|
+
:return: Starting X coordinate
|
|
1249
|
+
:rtype: float
|
|
1250
|
+
"""
|
|
998
1251
|
return self.__start_x
|
|
999
1252
|
|
|
1000
1253
|
@start_x.setter
|
|
@@ -1002,7 +1255,13 @@ class Scenario:
|
|
|
1002
1255
|
self.__start_x = value
|
|
1003
1256
|
|
|
1004
1257
|
@property
|
|
1005
|
-
def start_y(self):
|
|
1258
|
+
def start_y(self) -> float:
|
|
1259
|
+
"""
|
|
1260
|
+
Auxiliar variable determining the starting Y coordinate of the room
|
|
1261
|
+
|
|
1262
|
+
:return: Starting Y coordinate
|
|
1263
|
+
:rtype: float
|
|
1264
|
+
"""
|
|
1006
1265
|
return self.__start_y
|
|
1007
1266
|
|
|
1008
1267
|
@start_y.setter
|
|
@@ -1010,7 +1269,13 @@ class Scenario:
|
|
|
1010
1269
|
self.__start_y = value
|
|
1011
1270
|
|
|
1012
1271
|
@property
|
|
1013
|
-
def end_x(self):
|
|
1272
|
+
def end_x(self) -> float:
|
|
1273
|
+
"""
|
|
1274
|
+
Auxiliar variable determining the ending X coordinate of the room
|
|
1275
|
+
|
|
1276
|
+
:return: Ending X coordinate
|
|
1277
|
+
:rtype: float
|
|
1278
|
+
"""
|
|
1014
1279
|
return self.__end_x
|
|
1015
1280
|
|
|
1016
1281
|
@end_x.setter
|
|
@@ -1018,7 +1283,13 @@ class Scenario:
|
|
|
1018
1283
|
self.__end_x = value
|
|
1019
1284
|
|
|
1020
1285
|
@property
|
|
1021
|
-
def end_y(self):
|
|
1286
|
+
def end_y(self) -> float:
|
|
1287
|
+
"""
|
|
1288
|
+
Auxiliar variable determining the ending Y coordinate of the room
|
|
1289
|
+
|
|
1290
|
+
:return: Ending Y coordinate
|
|
1291
|
+
:rtype: float
|
|
1292
|
+
"""
|
|
1022
1293
|
return self.__end_y
|
|
1023
1294
|
|
|
1024
1295
|
@end_y.setter
|
|
@@ -1026,7 +1297,13 @@ class Scenario:
|
|
|
1026
1297
|
self.__end_y = value
|
|
1027
1298
|
|
|
1028
1299
|
@property
|
|
1029
|
-
def height(self):
|
|
1300
|
+
def height(self) -> float:
|
|
1301
|
+
"""
|
|
1302
|
+
Scenario height
|
|
1303
|
+
|
|
1304
|
+
:return: Scenario height
|
|
1305
|
+
:rtype: float
|
|
1306
|
+
"""
|
|
1030
1307
|
return self.__height
|
|
1031
1308
|
|
|
1032
1309
|
@height.setter
|
|
@@ -1034,7 +1311,13 @@ class Scenario:
|
|
|
1034
1311
|
self.__height = value
|
|
1035
1312
|
|
|
1036
1313
|
@property
|
|
1037
|
-
def length(self):
|
|
1314
|
+
def length(self) -> float:
|
|
1315
|
+
"""
|
|
1316
|
+
Scenario Length
|
|
1317
|
+
|
|
1318
|
+
:return: Scenario Length
|
|
1319
|
+
:rtype: float
|
|
1320
|
+
"""
|
|
1038
1321
|
return self.__length
|
|
1039
1322
|
|
|
1040
1323
|
@length.setter
|
|
@@ -1042,7 +1325,13 @@ class Scenario:
|
|
|
1042
1325
|
self.__length = value
|
|
1043
1326
|
|
|
1044
1327
|
@property
|
|
1045
|
-
def width(self):
|
|
1328
|
+
def width(self) -> float:
|
|
1329
|
+
"""
|
|
1330
|
+
Scenario width
|
|
1331
|
+
|
|
1332
|
+
:return: Scenario width
|
|
1333
|
+
:rtype: float
|
|
1334
|
+
"""
|
|
1046
1335
|
return self.__width
|
|
1047
1336
|
|
|
1048
1337
|
@width.setter
|
|
@@ -1050,14 +1339,36 @@ class Scenario:
|
|
|
1050
1339
|
self.__width = value
|
|
1051
1340
|
|
|
1052
1341
|
@property
|
|
1053
|
-
def vledsPositions(self):
|
|
1342
|
+
def vledsPositions(self) -> list:
|
|
1343
|
+
"""
|
|
1344
|
+
Vleds positions in room
|
|
1345
|
+
|
|
1346
|
+
:return: Vleds position
|
|
1347
|
+
:rtype: list
|
|
1348
|
+
"""
|
|
1054
1349
|
return self.__vledsPositions
|
|
1055
1350
|
|
|
1056
1351
|
@property
|
|
1057
|
-
def rfsPositions(self):
|
|
1352
|
+
def rfsPositions(self) -> list:
|
|
1353
|
+
"""
|
|
1354
|
+
RFs positions
|
|
1355
|
+
|
|
1356
|
+
:return: RFs positions
|
|
1357
|
+
:rtype: list
|
|
1358
|
+
"""
|
|
1058
1359
|
return self.__rfsPositions
|
|
1059
1360
|
|
|
1060
1361
|
def snrVled(self, receiver: Receiver, vled: VLed) -> float:
|
|
1362
|
+
"""
|
|
1363
|
+
Total SNR in an specific point from a VLED, considering walls and positions.
|
|
1364
|
+
|
|
1365
|
+
:param receiver: Receiver device
|
|
1366
|
+
:type receiver: Receiver
|
|
1367
|
+
:param vled: VLED
|
|
1368
|
+
:type vled: VLed
|
|
1369
|
+
:return: Total SNR
|
|
1370
|
+
:rtype: float
|
|
1371
|
+
"""
|
|
1061
1372
|
powerReceived = self.getPowerInPointFromVled(
|
|
1062
1373
|
receiver, vled.ID
|
|
1063
1374
|
) + self.getPowerInPointFromWalls(receiver, vled.ID)
|
|
@@ -1087,6 +1398,16 @@ class Scenario:
|
|
|
1087
1398
|
return (receiver.s * powerReceived) ** 2 / rg
|
|
1088
1399
|
|
|
1089
1400
|
def snrRf(self, receiver: Receiver, rf: RF) -> float:
|
|
1401
|
+
"""
|
|
1402
|
+
Total SNR in an specific point from an RF.
|
|
1403
|
+
|
|
1404
|
+
:param receiver: Receiver device
|
|
1405
|
+
:type receiver: Receiver
|
|
1406
|
+
:param rf: RF device
|
|
1407
|
+
:type rf: RF
|
|
1408
|
+
:return: Total SNR
|
|
1409
|
+
:rtype: float
|
|
1410
|
+
"""
|
|
1090
1411
|
df = m.sqrt(
|
|
1091
1412
|
(receiver.x - rf.x) ** 2
|
|
1092
1413
|
+ (receiver.y - rf.y) ** 2
|
|
@@ -1096,7 +1417,27 @@ class Scenario:
|
|
|
1096
1417
|
return rf.pf * rf.Af * df ** (-rf.Ef)
|
|
1097
1418
|
|
|
1098
1419
|
def capacityVled(self, receiver: Receiver, vled: VLed) -> float:
|
|
1420
|
+
"""
|
|
1421
|
+
Capacity of the VLED channel considering receiver devices in an specific point.
|
|
1422
|
+
|
|
1423
|
+
:param receiver: Receiver device
|
|
1424
|
+
:type receiver: Receiver
|
|
1425
|
+
:param vled: VLED
|
|
1426
|
+
:type vled: VLed
|
|
1427
|
+
:return: Capacity
|
|
1428
|
+
:rtype: float
|
|
1429
|
+
"""
|
|
1099
1430
|
return vled.B * m.log2(1 + self.snrVled(receiver, vled))
|
|
1100
1431
|
|
|
1101
1432
|
def capacityRf(self, receiver: Receiver, rf: RF) -> float:
|
|
1433
|
+
"""
|
|
1434
|
+
Capacity of the RF channel considering receiver devices in an specific point.
|
|
1435
|
+
|
|
1436
|
+
:param receiver: Receiver device
|
|
1437
|
+
:type receiver: Receiver
|
|
1438
|
+
:param rf: RF
|
|
1439
|
+
:type rf: RF
|
|
1440
|
+
:return: Capacity
|
|
1441
|
+
:rtype: float
|
|
1442
|
+
"""
|
|
1102
1443
|
return rf.B * m.log2(1 + self.snrRf(receiver, rf))
|
|
@@ -1,30 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The Module **Simulator** has all the Simulation Dynamics.
|
|
3
|
+
"""
|
|
4
|
+
|
|
1
5
|
from .controller import *
|
|
2
6
|
from .scene import *
|
|
3
7
|
import numpy as np
|
|
4
8
|
from enum import Enum
|
|
5
9
|
|
|
6
|
-
"""
|
|
7
|
-
The Module **Simulator** has all the Simulation Dynamics.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
10
|
|
|
11
11
|
class Event:
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
:param type: A handle to the :class:`simpleble.SimpleBleClient` client
|
|
16
|
-
object that detected the device
|
|
17
|
-
:type type: class:`Event.event`
|
|
18
|
-
:param time: Device MAC address, defaults to None
|
|
19
|
-
:type time: float, optional
|
|
20
|
-
:param id_connection: Device address type - one of ADDR_TYPE_PUBLIC or
|
|
21
|
-
ADDR_TYPE_RANDOM, defaults to ADDR_TYPE_PUBLIC
|
|
22
|
-
:type id_connection: int, optional
|
|
12
|
+
"""
|
|
13
|
+
The Event class has the information about the event, containing the time when the event occurs, the type of event, and the connection ID.
|
|
23
14
|
"""
|
|
24
15
|
|
|
25
16
|
event = Enum("event", "ARRIVE DEPARTURE PAUSE RESUME NEXT_CONNECTION_TRY")
|
|
17
|
+
"""
|
|
18
|
+
There are five event types. The **ARRIVE** event is used when a connection arrives to the scenario. **DEPARTURE** event when the connection leaves. **PAUSE** and **RESUME** is related to a connection that is currently served by an AP, but because of the frame-slot behavior is paused and resumed multiple times. Finally, **NEXT_CONNECTION_TRY** is used when a connection couldn't be stablished because capacity, and waits a random time and need to be served in future·
|
|
19
|
+
"""
|
|
26
20
|
|
|
27
|
-
def __init__(
|
|
21
|
+
def __init__(
|
|
22
|
+
self, type: event = None, time: float = -1, id_connection: int = -1
|
|
23
|
+
) -> None:
|
|
28
24
|
self.__time = time
|
|
29
25
|
self.__id_connection = id_connection
|
|
30
26
|
if type == None:
|
|
@@ -34,28 +30,70 @@ class Event:
|
|
|
34
30
|
self.__connection = None
|
|
35
31
|
|
|
36
32
|
@property
|
|
37
|
-
def type(self):
|
|
33
|
+
def type(self) -> event:
|
|
34
|
+
"""
|
|
35
|
+
The connection type. Could be one of the fives types described before.
|
|
36
|
+
|
|
37
|
+
:return: Connection type
|
|
38
|
+
:rtype: event
|
|
39
|
+
"""
|
|
38
40
|
return self.__type
|
|
39
41
|
|
|
40
42
|
@property
|
|
41
|
-
def time(self):
|
|
43
|
+
def time(self) -> float:
|
|
44
|
+
"""
|
|
45
|
+
The instant when this event occurs.
|
|
46
|
+
|
|
47
|
+
:return: Instant time of this event
|
|
48
|
+
:rtype: float
|
|
49
|
+
"""
|
|
42
50
|
return self.__time
|
|
43
51
|
|
|
44
52
|
@property
|
|
45
|
-
def id_connection(self):
|
|
53
|
+
def id_connection(self) -> int:
|
|
54
|
+
"""
|
|
55
|
+
Connection ID of the connection related to this event
|
|
56
|
+
|
|
57
|
+
:return: Connection ID
|
|
58
|
+
:rtype: int
|
|
59
|
+
"""
|
|
46
60
|
return self.__id_connection
|
|
47
61
|
|
|
48
62
|
@property
|
|
49
|
-
def connection(self):
|
|
63
|
+
def connection(self) -> Connection:
|
|
64
|
+
"""
|
|
65
|
+
Connection object related to this event.
|
|
66
|
+
|
|
67
|
+
:return: Connection object
|
|
68
|
+
:rtype: Connection
|
|
69
|
+
"""
|
|
50
70
|
return self.__connection
|
|
51
71
|
|
|
52
72
|
@connection.setter
|
|
53
|
-
def connection(self, value):
|
|
73
|
+
def connection(self, value: Connection):
|
|
54
74
|
self.__connection = value
|
|
55
75
|
|
|
56
76
|
|
|
57
77
|
class Simulator:
|
|
58
|
-
|
|
78
|
+
"""
|
|
79
|
+
Simulator class. In chanrge of randomness and the clock routine.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def __init__(self, x: float, y: float, z: float, nGrids: int, rho: float) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Simulator object constructor
|
|
85
|
+
|
|
86
|
+
:param x: Length of the scenario
|
|
87
|
+
:type x: float
|
|
88
|
+
:param y: Width of the scenario
|
|
89
|
+
:type y: float
|
|
90
|
+
:param z: Height of the scenario
|
|
91
|
+
:type z: float
|
|
92
|
+
:param nGrids: Number of segments on each dimension. Usefull for precision.
|
|
93
|
+
:type nGrids: int
|
|
94
|
+
:param rho: reflexion coefficient. A floating number between 0 and 1.
|
|
95
|
+
:type rho: float
|
|
96
|
+
"""
|
|
59
97
|
self.__controller = Controller(x, y, z, nGrids, rho)
|
|
60
98
|
self.__events = []
|
|
61
99
|
self.__current_event = None
|
|
@@ -98,6 +136,22 @@ class Simulator:
|
|
|
98
136
|
self.default_values()
|
|
99
137
|
|
|
100
138
|
def default_values(self):
|
|
139
|
+
"""
|
|
140
|
+
Set the default simulation values, that are:
|
|
141
|
+
|
|
142
|
+
* lambdaS = 3
|
|
143
|
+
* mu = 10
|
|
144
|
+
* seedArrive = 12345
|
|
145
|
+
* seedDeparture = 1234
|
|
146
|
+
* seedX = 1235
|
|
147
|
+
* seedY = 1245
|
|
148
|
+
* seedZ = 1345
|
|
149
|
+
* seedRandomWait = 1345
|
|
150
|
+
* seedCapacityRequired = 1345
|
|
151
|
+
* goalConnections = 10000
|
|
152
|
+
* lower_random_wait = 5
|
|
153
|
+
* upper_random_wait = 15
|
|
154
|
+
"""
|
|
101
155
|
self.__initReady = False
|
|
102
156
|
self.__lambdaS = 3
|
|
103
157
|
self.__mu = 10
|
|
@@ -113,9 +167,16 @@ class Simulator:
|
|
|
113
167
|
self.__goalConnections = 10000
|
|
114
168
|
self.__lower_random_wait = 5
|
|
115
169
|
self.__upper_random_wait = 15
|
|
170
|
+
self.__controller.allocator = Controller.default_alloc
|
|
116
171
|
|
|
117
172
|
@property
|
|
118
|
-
def upper_capacity_required(self):
|
|
173
|
+
def upper_capacity_required(self) -> float:
|
|
174
|
+
"""
|
|
175
|
+
The upper possible capacity required
|
|
176
|
+
|
|
177
|
+
:return: Upper capacity required
|
|
178
|
+
:rtype: float
|
|
179
|
+
"""
|
|
119
180
|
return self.__upper_capacity_required
|
|
120
181
|
|
|
121
182
|
@upper_capacity_required.setter
|
|
@@ -123,7 +184,13 @@ class Simulator:
|
|
|
123
184
|
self.__upper_capacity_required = value
|
|
124
185
|
|
|
125
186
|
@property
|
|
126
|
-
def lower_capacity_required(self):
|
|
187
|
+
def lower_capacity_required(self) -> float:
|
|
188
|
+
"""
|
|
189
|
+
The lower possible capacity required
|
|
190
|
+
|
|
191
|
+
:return: Lower capacity required
|
|
192
|
+
:rtype: float
|
|
193
|
+
"""
|
|
127
194
|
return self.__lower_capacity_required
|
|
128
195
|
|
|
129
196
|
@lower_capacity_required.setter
|
|
@@ -132,6 +199,12 @@ class Simulator:
|
|
|
132
199
|
|
|
133
200
|
@property
|
|
134
201
|
def seedCapacityRequired(self) -> int:
|
|
202
|
+
"""
|
|
203
|
+
Seed of capacity required random generator
|
|
204
|
+
|
|
205
|
+
:return: random generator seed
|
|
206
|
+
:rtype: int
|
|
207
|
+
"""
|
|
135
208
|
return self.__seedCapacityRequired
|
|
136
209
|
|
|
137
210
|
@seedCapacityRequired.setter
|
|
@@ -139,7 +212,13 @@ class Simulator:
|
|
|
139
212
|
self.__seedCapacityRequired = value
|
|
140
213
|
|
|
141
214
|
@property
|
|
142
|
-
def upper_random_wait(self):
|
|
215
|
+
def upper_random_wait(self) -> float:
|
|
216
|
+
"""
|
|
217
|
+
the upper possible random wait
|
|
218
|
+
|
|
219
|
+
:return: upper waiting time
|
|
220
|
+
:rtype: float
|
|
221
|
+
"""
|
|
143
222
|
return self.__upper_random_wait
|
|
144
223
|
|
|
145
224
|
@upper_random_wait.setter
|
|
@@ -147,7 +226,13 @@ class Simulator:
|
|
|
147
226
|
self.__upper_random_wait = value
|
|
148
227
|
|
|
149
228
|
@property
|
|
150
|
-
def lower_random_wait(self):
|
|
229
|
+
def lower_random_wait(self) -> float:
|
|
230
|
+
"""
|
|
231
|
+
The lower possible random wait
|
|
232
|
+
|
|
233
|
+
:return: lower waiting time
|
|
234
|
+
:rtype: float
|
|
235
|
+
"""
|
|
151
236
|
return self.__lower_random_wait
|
|
152
237
|
|
|
153
238
|
@lower_random_wait.setter
|
|
@@ -155,9 +240,12 @@ class Simulator:
|
|
|
155
240
|
self.__lower_random_wait = value
|
|
156
241
|
|
|
157
242
|
@property
|
|
158
|
-
def lambdaS(self):
|
|
243
|
+
def lambdaS(self) -> float:
|
|
159
244
|
"""
|
|
160
245
|
Get or set the attribute lambda.
|
|
246
|
+
|
|
247
|
+
:return: lambda attribute
|
|
248
|
+
:rtype: float
|
|
161
249
|
"""
|
|
162
250
|
return self.__lambdaS
|
|
163
251
|
|
|
@@ -171,9 +259,12 @@ class Simulator:
|
|
|
171
259
|
self.__lambdaS = lambdaS
|
|
172
260
|
|
|
173
261
|
@property
|
|
174
|
-
def mu(self):
|
|
262
|
+
def mu(self) -> float:
|
|
175
263
|
"""
|
|
176
264
|
Get or set the attribute mu.
|
|
265
|
+
|
|
266
|
+
:return: mu attribute
|
|
267
|
+
:rtype: float
|
|
177
268
|
"""
|
|
178
269
|
return self.__mu
|
|
179
270
|
|
|
@@ -187,9 +278,12 @@ class Simulator:
|
|
|
187
278
|
self.__mu = mu
|
|
188
279
|
|
|
189
280
|
@property
|
|
190
|
-
def seedX(self):
|
|
281
|
+
def seedX(self) -> int:
|
|
191
282
|
"""
|
|
192
|
-
Get or set the attribute
|
|
283
|
+
Get or set the attribute seedX.
|
|
284
|
+
|
|
285
|
+
:return: the seed of random X generator
|
|
286
|
+
:rtype: int
|
|
193
287
|
"""
|
|
194
288
|
return self.__seedX
|
|
195
289
|
|
|
@@ -203,9 +297,12 @@ class Simulator:
|
|
|
203
297
|
self.__seedX = seedX
|
|
204
298
|
|
|
205
299
|
@property
|
|
206
|
-
def seedY(self):
|
|
300
|
+
def seedY(self) -> int:
|
|
207
301
|
"""
|
|
208
|
-
Get or set the attribute
|
|
302
|
+
Get or set the attribute seedY.
|
|
303
|
+
|
|
304
|
+
:return: the seed of random Y generator
|
|
305
|
+
:rtype: int
|
|
209
306
|
"""
|
|
210
307
|
return self.__seedY
|
|
211
308
|
|
|
@@ -219,9 +316,12 @@ class Simulator:
|
|
|
219
316
|
self.__seedY = seedY
|
|
220
317
|
|
|
221
318
|
@property
|
|
222
|
-
def seedZ(self):
|
|
319
|
+
def seedZ(self) -> int:
|
|
223
320
|
"""
|
|
224
|
-
Get or set the attribute
|
|
321
|
+
Get or set the attribute seedZ.
|
|
322
|
+
|
|
323
|
+
:return: the seed of random Z generator
|
|
324
|
+
:rtype: int
|
|
225
325
|
"""
|
|
226
326
|
return self.__seedZ
|
|
227
327
|
|
|
@@ -235,9 +335,12 @@ class Simulator:
|
|
|
235
335
|
self.__seedZ = seedZ
|
|
236
336
|
|
|
237
337
|
@property
|
|
238
|
-
def seedRandomWait(self):
|
|
338
|
+
def seedRandomWait(self) -> int:
|
|
239
339
|
"""
|
|
240
|
-
Get or set the attribute
|
|
340
|
+
Get or set the attribute seedRandomWait.
|
|
341
|
+
|
|
342
|
+
:return: the seed of random random-wait generator
|
|
343
|
+
:rtype: int
|
|
241
344
|
"""
|
|
242
345
|
return self.__seedRandomWait
|
|
243
346
|
|
|
@@ -251,9 +354,12 @@ class Simulator:
|
|
|
251
354
|
self.__seedRandomWait = seedRandomWait
|
|
252
355
|
|
|
253
356
|
@property
|
|
254
|
-
def goalConnections(self):
|
|
357
|
+
def goalConnections(self) -> int:
|
|
255
358
|
"""
|
|
256
359
|
Get or set the attribute goalConnections.
|
|
360
|
+
|
|
361
|
+
:return: The goal connections
|
|
362
|
+
:rtype: int
|
|
257
363
|
"""
|
|
258
364
|
return self.__goalConnections
|
|
259
365
|
|
|
@@ -267,6 +373,9 @@ class Simulator:
|
|
|
267
373
|
self.__goalConnections = goalConnections
|
|
268
374
|
|
|
269
375
|
def print_initial_info(self):
|
|
376
|
+
"""
|
|
377
|
+
Prints the initial info of simulation.
|
|
378
|
+
"""
|
|
270
379
|
print(
|
|
271
380
|
"Scenario:\t %s x %s x %s"
|
|
272
381
|
% (
|
|
@@ -314,6 +423,12 @@ class Simulator:
|
|
|
314
423
|
print("=" * 146)
|
|
315
424
|
|
|
316
425
|
def print_row(self, event):
|
|
426
|
+
"""
|
|
427
|
+
print every simulation row
|
|
428
|
+
|
|
429
|
+
:param event: The event to print_
|
|
430
|
+
:type event: Event
|
|
431
|
+
"""
|
|
317
432
|
text = ""
|
|
318
433
|
text = "{:9.4f}".format(event.time) + "|"
|
|
319
434
|
if event.type == Event.event.ARRIVE:
|
|
@@ -372,6 +487,9 @@ class Simulator:
|
|
|
372
487
|
print(text)
|
|
373
488
|
|
|
374
489
|
def event_routine(self):
|
|
490
|
+
"""
|
|
491
|
+
The event routine. This function selects the event and run the associated routine.
|
|
492
|
+
"""
|
|
375
493
|
self.__current_event = self.__events[0]
|
|
376
494
|
self.__rtn_allocation = None
|
|
377
495
|
self.__clock = self.__current_event.time
|
|
@@ -550,11 +668,13 @@ class Simulator:
|
|
|
550
668
|
# self.__events.insert(pos + 1, e)
|
|
551
669
|
# break
|
|
552
670
|
self.__events.pop(0)
|
|
553
|
-
self.print_row(self.__current_event)
|
|
554
671
|
|
|
555
672
|
return self.__rtn_allocation
|
|
556
673
|
|
|
557
674
|
def init(self):
|
|
675
|
+
"""
|
|
676
|
+
Simulation init. Initialize every simulation parameter.
|
|
677
|
+
"""
|
|
558
678
|
self.__initReady = True
|
|
559
679
|
self.__clock = 0
|
|
560
680
|
self.__arrival_variable = np.random.default_rng(self.__seedArrive)
|
|
@@ -586,29 +706,59 @@ class Simulator:
|
|
|
586
706
|
return
|
|
587
707
|
|
|
588
708
|
def run(self):
|
|
709
|
+
"""
|
|
710
|
+
Run this simulation with the parameters.
|
|
711
|
+
"""
|
|
589
712
|
self.print_initial_info()
|
|
590
713
|
while self.__numberOfConnections <= self.__goalConnections:
|
|
591
714
|
# for i in range(self.__goalConnections):
|
|
592
715
|
self.event_routine()
|
|
716
|
+
self.print_row(self.__current_event)
|
|
593
717
|
self.aggregated_metrics()
|
|
594
718
|
|
|
595
|
-
def time_duration(self):
|
|
719
|
+
def time_duration(self) -> float:
|
|
720
|
+
"""
|
|
721
|
+
Duration time
|
|
722
|
+
|
|
723
|
+
:return: duration time
|
|
724
|
+
:rtype: float
|
|
725
|
+
"""
|
|
596
726
|
return self.__time_duration
|
|
597
727
|
|
|
598
|
-
def get_Blocking_Probability(self):
|
|
728
|
+
def get_Blocking_Probability(self) -> float:
|
|
729
|
+
"""
|
|
730
|
+
Blocking probability
|
|
731
|
+
|
|
732
|
+
:return: blocking probability
|
|
733
|
+
:rtype: float
|
|
734
|
+
"""
|
|
599
735
|
blocking = round(
|
|
600
736
|
1 - self.__allocatedConnections / self.__numberOfConnections, 2
|
|
601
737
|
)
|
|
602
738
|
return blocking
|
|
603
739
|
|
|
604
740
|
def set_allocation_algorithm(self, alloc_alg):
|
|
741
|
+
"""
|
|
742
|
+
Set allocation algorithm.
|
|
743
|
+
|
|
744
|
+
:param alloc_alg: Allocation algorithm
|
|
745
|
+
"""
|
|
605
746
|
self.__controller.allocator = alloc_alg
|
|
606
747
|
|
|
607
748
|
@property
|
|
608
749
|
def scenario(self):
|
|
750
|
+
"""
|
|
751
|
+
Scenario used in this simulation
|
|
752
|
+
|
|
753
|
+
:return: Scenario
|
|
754
|
+
:rtype: Scenario
|
|
755
|
+
"""
|
|
609
756
|
return self.__controller.scenario
|
|
610
757
|
|
|
611
758
|
def aggregated_metrics(self):
|
|
759
|
+
"""
|
|
760
|
+
Number of users connected to each AP
|
|
761
|
+
"""
|
|
612
762
|
print("Number of users connected to each VLed")
|
|
613
763
|
for i in range(self.__controller.scenario.numberOfVLeds):
|
|
614
764
|
id = self.__controller.scenario.vleds[i].ID
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|