zipf: Small changes (style and small logic correction) and adding documentation section
diff --git a/apps/ndn-consumer-cbr.h b/apps/ndn-consumer-cbr.h
index 8ab4472..01e84a5 100644
--- a/apps/ndn-consumer-cbr.h
+++ b/apps/ndn-consumer-cbr.h
@@ -88,7 +88,6 @@
// DataRate
// GetDesiredRate () const;
-private:
protected:
double m_frequency; // Frequency of interest packets (in hertz)
bool m_firstTime;
diff --git a/apps/ndn-consumer-zipf-mandelbrot.cc b/apps/ndn-consumer-zipf-mandelbrot.cc
index d744143..1fc8d45 100644
--- a/apps/ndn-consumer-zipf-mandelbrot.cc
+++ b/apps/ndn-consumer-zipf-mandelbrot.cc
@@ -24,7 +24,6 @@
#include "ns3/ndn-interest.h"
#include "ns3/ndn-content-object.h"
#include <math.h>
-//#include <random-variable.h>
NS_LOG_COMPONENT_DEFINE ("ndn.ConsumerZipfMandelbrot");
@@ -41,18 +40,22 @@
.SetGroupName ("Ndn")
.SetParent<ConsumerCbr> ()
.AddConstructor<ConsumerZipfMandelbrot> ()
- .AddAttribute ("N", "Number of the Contents in total",
- StringValue ("100"),
- MakeUintegerAccessor (&ConsumerZipfMandelbrot::m_N),
- MakeUintegerChecker<uint32_t> ())
- .AddAttribute ("q", "parameter of improve rank",
- StringValue ("0.7"),
- MakeDoubleAccessor (&ConsumerZipfMandelbrot::m_q),
- MakeDoubleChecker<double>())
- .AddAttribute ("s", "parameter of power",
- StringValue ("0.7"),
- MakeDoubleAccessor (&ConsumerZipfMandelbrot::m_s),
- MakeDoubleChecker<double>())
+
+ .AddAttribute ("NumberOfContents", "Number of the Contents in total",
+ StringValue ("100"),
+ MakeUintegerAccessor (&ConsumerZipfMandelbrot::SetNumberOfContents, &ConsumerZipfMandelbrot::GetNumberOfContents),
+ MakeUintegerChecker<uint32_t> ())
+
+ // Alex: q and s are not yet really working
+ //
+ // .AddAttribute ("q", "parameter of improve rank",
+ // StringValue ("0.7"),
+ // MakeDoubleAccessor (&ConsumerZipfMandelbrot::m_q),
+ // MakeDoubleChecker<double>())
+ // .AddAttribute ("s", "parameter of power",
+ // StringValue ("0.7"),
+ // MakeDoubleAccessor (&ConsumerZipfMandelbrot::m_s),
+ // MakeDoubleChecker<double>())
;
return tid;
@@ -60,149 +63,162 @@
ConsumerZipfMandelbrot::ConsumerZipfMandelbrot()
- : m_N(100)
- , m_q (0.7)
- , m_s (0.7)
+ : m_q (0.7)
+ , m_s (0.7)
+ , m_SeqRng (0.0, 1.0)
{
- m_Pcum = new double[m_N+1];
- m_Pcum[0] = 0.0;
- for (uint32_t i=1; i<=m_N; i++) {
- m_Pcum[i] = m_Pcum[i-1] + 1.0/pow(i+m_q, m_s);
- }
- for (uint32_t i=1; i<=m_N; i++) {
- m_Pcum[i] = m_Pcum[i] / m_Pcum[m_N];
- NS_LOG_LOGIC("cum Probability ["<<i<<"]="<<m_Pcum[i]);
- }
- //Ptr<UniformRandomVariable> m_SeqRng = CreateObject<UniformRandomVariable> ();
- m_SeqRng = new UniformVariable(0.0, 1.0); //[1, m_N+1)
- //m_SeqRng = new UniformVariable ();
+ // SetNumberOfContents is called by NS-3 object system during the initialization
}
-ConsumerZipfMandelbrot::~ConsumerZipfMandelbrot() {
- if (m_Pcum) {
- delete m_Pcum;
- m_Pcum = NULL;
- }
-// if (m_SeqRng) {
-// delete m_SeqRng;
-// m_SeqRng = NULL;
-// }
+ConsumerZipfMandelbrot::~ConsumerZipfMandelbrot()
+{
}
void
+ConsumerZipfMandelbrot::SetNumberOfContents (uint32_t numOfContents)
+{
+ m_N = numOfContents;
+
+ m_Pcum = std::vector<double> (m_N + 1);
+
+ m_Pcum[0] = 0.0;
+ for (uint32_t i=1; i<=m_N; i++)
+ {
+ m_Pcum[i] = m_Pcum[i-1] + 1.0/pow(i+m_q, m_s);
+ }
+
+ for (uint32_t i=1; i<=m_N; i++)
+ {
+ m_Pcum[i] = m_Pcum[i] / m_Pcum[m_N];
+ NS_LOG_LOGIC("cum Probability ["<<i<<"]="<<m_Pcum[i]);
+ }
+}
+
+uint32_t
+ConsumerZipfMandelbrot::GetNumberOfContents () const
+{
+ return m_N;
+}
+
+
+void
ConsumerZipfMandelbrot::SendPacket() {
- if (!m_active) return;
+ if (!m_active) return;
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION_NOARGS ();
- uint32_t seq=std::numeric_limits<uint32_t>::max (); //invalid
+ uint32_t seq=std::numeric_limits<uint32_t>::max (); //invalid
- // std::cout << Simulator::Now ().ToDouble (Time::S) << "s max -> " << m_seqMax << "\n";
+ // std::cout << Simulator::Now ().ToDouble (Time::S) << "s max -> " << m_seqMax << "\n";
- while (m_retxSeqs.size ())
- {
- seq = *m_retxSeqs.begin ();
- m_retxSeqs.erase (m_retxSeqs.begin ());
+ while (m_retxSeqs.size ())
+ {
+ seq = *m_retxSeqs.begin ();
+ m_retxSeqs.erase (m_retxSeqs.begin ());
- // NS_ASSERT (m_seqLifetimes.find (seq) != m_seqLifetimes.end ());
- // if (m_seqLifetimes.find (seq)->time <= Simulator::Now ())
- // {
+ // NS_ASSERT (m_seqLifetimes.find (seq) != m_seqLifetimes.end ());
+ // if (m_seqLifetimes.find (seq)->time <= Simulator::Now ())
+ // {
- // NS_LOG_DEBUG ("Expire " << seq);
- // m_seqLifetimes.erase (seq); // lifetime expired. Trying to find another unexpired sequence number
- // continue;
- // }
- NS_LOG_DEBUG("=interest seq "<<seq<<" from m_retxSeqs");
- break;
- }
+ // NS_LOG_DEBUG ("Expire " << seq);
+ // m_seqLifetimes.erase (seq); // lifetime expired. Trying to find another unexpired sequence number
+ // continue;
+ // }
+ NS_LOG_DEBUG("=interest seq "<<seq<<" from m_retxSeqs");
+ break;
+ }
- if (seq == std::numeric_limits<uint32_t>::max ()) //no retransmission
- {
- if (m_seqMax != std::numeric_limits<uint32_t>::max ())
- {
- if (m_seq >= m_seqMax)
- {
- return; // we are totally done
- }
- }
+ if (seq == std::numeric_limits<uint32_t>::max ()) //no retransmission
+ {
+ if (m_seqMax != std::numeric_limits<uint32_t>::max ())
+ {
+ if (m_seq >= m_seqMax)
+ {
+ return; // we are totally done
+ }
+ }
- seq = ConsumerZipfMandelbrot::GetNextSeq();
- m_seq ++;
- }
+ seq = ConsumerZipfMandelbrot::GetNextSeq();
+ m_seq ++;
+ }
- // std::cout << Simulator::Now ().ToDouble (Time::S) << "s -> " << seq << "\n";
+ // std::cout << Simulator::Now ().ToDouble (Time::S) << "s -> " << seq << "\n";
- //
- Ptr<NameComponents> nameWithSequence = Create<NameComponents> (m_interestName);
- (*nameWithSequence) (seq);
- //
+ //
+ Ptr<NameComponents> nameWithSequence = Create<NameComponents> (m_interestName);
+ (*nameWithSequence) (seq);
+ //
- InterestHeader interestHeader;
- interestHeader.SetNonce (m_rand.GetValue ());
- interestHeader.SetName (nameWithSequence);
+ InterestHeader interestHeader;
+ interestHeader.SetNonce (m_rand.GetValue ());
+ interestHeader.SetName (nameWithSequence);
- // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
- NS_LOG_INFO ("> Interest for " << seq<<", Total: "<<m_seq<<", face: "<<m_face->GetId());
+ // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
+ NS_LOG_INFO ("> Interest for " << seq<<", Total: "<<m_seq<<", face: "<<m_face->GetId());
- Ptr<Packet> packet = Create<Packet> ();
+ Ptr<Packet> packet = Create<Packet> ();
- //NS_LOG_DEBUG ("= Interest for " << seq<<", Total: "<<m_seq<<", face: "<<m_face->GetId());
- packet->AddHeader (interestHeader);
- //NS_LOG_DEBUG ("Interest packet size: " << packet->GetSize ());
+ //NS_LOG_DEBUG ("= Interest for " << seq<<", Total: "<<m_seq<<", face: "<<m_face->GetId());
+ packet->AddHeader (interestHeader);
+ //NS_LOG_DEBUG ("Interest packet size: " << packet->GetSize ());
- NS_LOG_DEBUG ("Trying to add " << seq << " with " << Simulator::Now () << ". already " << m_seqTimeouts.size () << " items");
+ NS_LOG_DEBUG ("Trying to add " << seq << " with " << Simulator::Now () << ". already " << m_seqTimeouts.size () << " items");
- m_seqTimeouts.insert (SeqTimeout (seq, Simulator::Now ()));
- m_seqLifetimes.insert (SeqTimeout (seq, Simulator::Now () + m_interestLifeTime)); // only one insert will work. if entry exists, nothing will happen... nothing should happen
- m_transmittedInterests (&interestHeader, this, m_face);
+ m_seqTimeouts.insert (SeqTimeout (seq, Simulator::Now ()));
+ m_seqLifetimes.insert (SeqTimeout (seq, Simulator::Now () + m_interestLifeTime)); // only one insert will work. if entry exists, nothing will happen... nothing should happen
+ m_transmittedInterests (&interestHeader, this, m_face);
- m_rtt->SentSeq (SequenceNumber32 (seq), 1);
+ m_rtt->SentSeq (SequenceNumber32 (seq), 1);
- m_protocolHandler (packet);
+ m_protocolHandler (packet);
- ConsumerZipfMandelbrot::ScheduleNextPacket ();
+ ConsumerZipfMandelbrot::ScheduleNextPacket ();
}
uint32_t
-ConsumerZipfMandelbrot::GetNextSeq(){
- uint32_t content_index = 1; //[1, m_N]
- double p_sum = 0;
+ConsumerZipfMandelbrot::GetNextSeq()
+{
+ uint32_t content_index = 1; //[1, m_N]
+ double p_sum = 0;
- double p_random = m_SeqRng->GetValue();
- while (p_random == 0){
- p_random = m_SeqRng->GetValue();
- }
- //if (p_random == 0)
- NS_LOG_LOGIC("p_random="<<p_random);
- for (uint32_t i=1; i<=m_N; i++) {
- p_sum = m_Pcum[i]; //m_Pcum[i] = m_Pcum[i-1] + p[i], p[0] = 0; e.g.: p_cum[1] = p[1], p_cum[2] = p[1] + p[2]
- if (p_random <= p_sum) {
- content_index = i;
- break;
- } //if
- } //for
- //content_index = 1;
- NS_LOG_DEBUG("RandomNumber="<<content_index);
- return content_index;
+ double p_random = m_SeqRng.GetValue();
+ while (p_random == 0)
+ {
+ p_random = m_SeqRng.GetValue();
+ }
+ //if (p_random == 0)
+ NS_LOG_LOGIC("p_random="<<p_random);
+ for (uint32_t i=1; i<=m_N; i++)
+ {
+ p_sum = m_Pcum[i]; //m_Pcum[i] = m_Pcum[i-1] + p[i], p[0] = 0; e.g.: p_cum[1] = p[1], p_cum[2] = p[1] + p[2]
+ if (p_random <= p_sum)
+ {
+ content_index = i;
+ break;
+ } //if
+ } //for
+ //content_index = 1;
+ NS_LOG_DEBUG("RandomNumber="<<content_index);
+ return content_index;
}
void
ConsumerZipfMandelbrot::ScheduleNextPacket() {
- if (m_firstTime)
- {
- m_sendEvent = Simulator::Schedule (Seconds (0.0),
- &ConsumerZipfMandelbrot::SendPacket, this);
- m_firstTime = false;
- }
- else if (!m_sendEvent.IsRunning ())
- m_sendEvent = Simulator::Schedule (
- (m_random == 0) ?
- Seconds(1.0 / m_frequency)
- :
- Seconds(m_random->GetValue ()),
- &ConsumerZipfMandelbrot::SendPacket, this);
+ if (m_firstTime)
+ {
+ m_sendEvent = Simulator::Schedule (Seconds (0.0),
+ &ConsumerZipfMandelbrot::SendPacket, this);
+ m_firstTime = false;
+ }
+ else if (!m_sendEvent.IsRunning ())
+ m_sendEvent = Simulator::Schedule (
+ (m_random == 0) ?
+ Seconds(1.0 / m_frequency)
+ :
+ Seconds(m_random->GetValue ()),
+ &ConsumerZipfMandelbrot::SendPacket, this);
}
} /* namespace ndn */
diff --git a/apps/ndn-consumer-zipf-mandelbrot.h b/apps/ndn-consumer-zipf-mandelbrot.h
index 7d72ef3..71113b2 100644
--- a/apps/ndn-consumer-zipf-mandelbrot.h
+++ b/apps/ndn-consumer-zipf-mandelbrot.h
@@ -43,38 +43,41 @@
*
* The class implements an app which requests contents following Zipf-Mandelbrot Distribution
* Here is the explaination of Zipf-Mandelbrot Distribution: http://en.wikipedia.org/wiki/Zipf%E2%80%93Mandelbrot_law
-
*/
-//
-class ConsumerZipfMandelbrot: public ns3::ndn::ConsumerCbr {
+class ConsumerZipfMandelbrot: public ConsumerCbr
+{
public:
- static TypeId GetTypeId ();
+ static TypeId GetTypeId ();
/**
* \brief Default constructor
* Sets up randomized Number Generator (RNG)
* Note: m_seq of its parent class ConsumerCbr here is used to record the interest number
*/
- ConsumerZipfMandelbrot();
- virtual ~ConsumerZipfMandelbrot();
+ ConsumerZipfMandelbrot ();
+ virtual ~ConsumerZipfMandelbrot ();
- virtual void SendPacket();
- uint32_t GetNextSeq();
+ virtual void SendPacket();
+ uint32_t GetNextSeq();
protected:
- virtual void
- ScheduleNextPacket ();
+ virtual void
+ ScheduleNextPacket ();
private:
- uint32_t m_N; //number of the contents
- double m_q; //q in (k+q)^s
- double m_s; //s in (k+q)^s
- double * m_Pcum; //cumulative probability
+ void
+ SetNumberOfContents (uint32_t numOfContents);
- UniformVariable * m_SeqRng; //RNG
+ uint32_t
+ GetNumberOfContents () const;
+
+private:
+ uint32_t m_N; //number of the contents
+ double m_q; //q in (k+q)^s
+ double m_s; //s in (k+q)^s
+ std::vector<double> m_Pcum; //cumulative probability
-
-
+ UniformVariable m_SeqRng; //RNG
};
} /* namespace ndn */
diff --git a/docs/source/_static/apps/zipf-n100-frq100-duration10.png b/docs/source/_static/apps/zipf-n100-frq100-duration10.png
new file mode 100644
index 0000000..b9918f3
--- /dev/null
+++ b/docs/source/_static/apps/zipf-n100-frq100-duration10.png
Binary files differ
diff --git a/docs/source/_static/apps/zipf-n100-frq100-duration100.png b/docs/source/_static/apps/zipf-n100-frq100-duration100.png
new file mode 100644
index 0000000..c560df5
--- /dev/null
+++ b/docs/source/_static/apps/zipf-n100-frq100-duration100.png
Binary files differ
diff --git a/docs/source/_static/apps/zipf-n100-frq100-duration1000.png b/docs/source/_static/apps/zipf-n100-frq100-duration1000.png
new file mode 100644
index 0000000..25818f9
--- /dev/null
+++ b/docs/source/_static/apps/zipf-n100-frq100-duration1000.png
Binary files differ
diff --git a/docs/source/_static/apps/zipf-n100-frq100-duration50.png b/docs/source/_static/apps/zipf-n100-frq100-duration50.png
new file mode 100644
index 0000000..ecc4291
--- /dev/null
+++ b/docs/source/_static/apps/zipf-n100-frq100-duration50.png
Binary files differ
diff --git a/docs/source/applications.rst b/docs/source/applications.rst
index bef7395..97aa326 100644
--- a/docs/source/applications.rst
+++ b/docs/source/applications.rst
@@ -18,7 +18,7 @@
This applications has the following attributes:
-* Frequency
+* ``Frequency``
.. note::
default: ``1.0`` (1 per second)
@@ -30,7 +30,7 @@
// Set attribute using the app helper
helper.SetAttribute ("Frequency", DoubleValue (1.0));
-* Randomize
+* ``Randomize``
.. note::
default: ``"none"``
@@ -48,6 +48,47 @@
// Set attribute using the app helper
helper.SetAttribute ("Randomize", StringValue ("uniform"));
+ConsumerZipfMandelbrot
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. note::
+ Author: Xiaoke Jiang
+
+An app that requests contents (names in the requests) following Zipf-Mandelbrot distribution (number of Content frequency Distribution).
+This class is a subclass of :ndnsim:`ConsumerCbr`.
+
+.. code-block:: c++
+
+ // Create application using the app helper
+ ndn::AppHelper helper ("ns3::ndn::ConsumerZipfMandelbrot");
+
+``Frequency`` and ``Randomize`` attributes can be used in the same way as in the base :ndnsim:`ConsumerCbr` applications.
+
+Additional attributes:
+
+* ``NumberOfContents``
+
+ .. note::
+ default: 100
+
+ Number of different content (sequence numbers) that will be requested by the applications
+
+
+THE following pictures show basic comparison of the generated stream of Interests versus theoretical `Zipf-Mandelbrot <http://en.wikipedia.org/wiki/Zipf%E2%80%93Mandelbrot_law>`_ function (``NumberOfContents`` set to 100 and ``Frequency`` set to 100)
+
+.. image:: _static/apps/zipf-n100-frq100-duration10.png
+ :alt: Comparsion between simulation and theory with simulation duration 10 seconds
+
+.. image:: _static/apps/zipf-n100-frq100-duration50.png
+ :alt: Comparsion between simulation and theory with simulation duration 50 seconds
+
+.. image:: _static/apps/zipf-n100-frq100-duration100.png
+ :alt: Comparsion between simulation and theory with simulation duration 100 seconds
+
+.. image:: _static/apps/zipf-n100-frq100-duration1000.png
+ :alt: Comparsion between simulation and theory with simulation duration 1000 seconds
+
+
ConsumerBatches
^^^^^^^^^^^^^^^^^^^
@@ -60,7 +101,7 @@
This applications has the following attributes:
-* Batches
+* ``Batches``
.. note::
default: Empty
@@ -87,21 +128,21 @@
This applications has the following attributes:
-* Window
+* ``Window``
.. note::
default: ``1``
Initial number of Interests that will be send out without waiting for the data (number of outstanding Interests)
-* PayloadSize
+* ``PayloadSize``
.. note::
default: ``1040``
Expected size of the Data payload (necessary only when Size is specified)
-* Size
+* ``Size``
.. note::
default: ``-1``
@@ -223,3 +264,4 @@
:linenos:
:lines: 21-
+
diff --git a/examples/zipf-mandelbrot.cc b/examples/ndn-zipf-mandelbrot.cc
similarity index 84%
rename from examples/zipf-mandelbrot.cc
rename to examples/ndn-zipf-mandelbrot.cc
index b775973..64e385c 100644
--- a/examples/zipf-mandelbrot.cc
+++ b/examples/ndn-zipf-mandelbrot.cc
@@ -47,17 +47,13 @@
*
* To run scenario and see what is happening, use the following command:
*
- * NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-grid
+ * NS_LOG=ndn.Consumer:ndn.ConsumerZipfMandelbrot:ndn.Producer ./waf --run=ndn-zipf-mandelbrot
*/
int
main (int argc, char *argv[])
{
- LogComponentEnable("ndn.ConsumerZipfMandelbrot", LOG_LEVEL_DEBUG);
- LogComponentEnable("ndn.ConsumerCbr", LOG_LEVEL_INFO);
- LogComponentEnable("ndn.Producer", LOG_LEVEL_INFO);
- LogComponentEnable("ndn.Consumer", LOG_LEVEL_INFO);
- //LogComponentEnable("ndn.CbisGlobalRoutingHelper", LOG_LEVEL_INFO);
+ //LogComponentEnable("ndn.CbisGlobalRoutingHelper", LOG_LEVEL_INFO);
// Setting default parameters for PointToPoint links and channels
Config::SetDefault ("ns3::PointToPointNetDevice::DataRate", StringValue ("1Mbps"));
Config::SetDefault ("ns3::PointToPointChannel::Delay", StringValue ("1ms"));
@@ -95,6 +91,7 @@
//ndn::AppHelper consumerHelper ("ns3::ndn::ConsumerCbr");
consumerHelper.SetPrefix (prefix);
consumerHelper.SetAttribute ("Frequency", StringValue ("100")); // 100 interests a second
+ consumerHelper.SetAttribute ("NumberOfContents", StringValue ("100")); // 10 different contents
//consumerHelper.SetAttribute ("Randomize", StringValue ("uniform")); // 100 interests a second
consumerHelper.Install (consumerNodes);
@@ -104,23 +101,9 @@
producerHelper.Install (producer);
ccnxGlobalRoutingHelper.AddOrigins (prefix, producer);
- //Ptr<Node> producer2 = grid.GetNode(1,2);
- //producerHelper.Install (producer2);
- // Add /prefix origins to ndn::GlobalRouter
- //ccnxGlobalRoutingHelper.AddOrigins (prefix, producer2);
-
-
-
-
- // Add /prefix origins to ndn::GlobalRouter
- //ccnxGlobalRoutingHelper.AddOrigins (prefix, producer);
-
-
// Calculate and install FIBs
ccnxGlobalRoutingHelper.CalculateRoutes ();
- //ccnxGlobalRoutingHelper.CalculateRoutes2 ();
-
Simulator::Stop (Seconds (10.0));
Simulator::Run ();
diff --git a/examples/wscript b/examples/wscript
index c00bad6..c3fc672 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -7,8 +7,8 @@
obj = bld.create_ns3_program('ndn-grid', ['ndnSIM', 'point-to-point-layout'])
obj.source = 'ndn-grid.cc'
- obj = bld.create_ns3_program('zipf-mandelbrot', ['ndnSIM', 'point-to-point-layout'])
- obj.source = 'zipf-mandelbrot.cc'
+ obj = bld.create_ns3_program('ndn-zipf-mandelbrot', ['ndnSIM', 'point-to-point-layout'])
+ obj.source = 'ndn-zipf-mandelbrot.cc'
obj = bld.create_ns3_program('ndn-simple-with-content-freshness', ['ndnSIM'])