/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2020 Lawrence Livermore National Laboratory * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Peter D. Barnes, Jr. */ #include "ns3/simulator.h" #include "ns3/nstime.h" #include "ns3/command-line.h" #include "ns3/random-variable-stream.h" #include "ns3/histogram.h" #include "ns3/ptr.h" #include #include #include /** * \file * \ingroup core-examples * \ingroup randomvariable * Example program illustrating use of ns3::EmpiricalRandomVariable * * This example illustrates * * * Creating an EmpiricalRandomVariable instance. * * Switching the mode. * * Using the sampling mode * * Switching modes * * Using the interpolating mode * * Consult the ns-3 manual for more information about the use of the * random number generator */ using namespace ns3; void RunSingleSample (std::string mode, Ptr erv) { std::cout << "------------------------------" << std::endl; std::cout << "Sampling " << mode << std::endl; std::cout << std::endl; std::cout << "Binned sample" << std::endl; double value = erv->GetValue (); std::cout << "Binned sample: " << value << std::endl; std::cout << std::endl; std::cout << "Interpolated sample" << std::endl; erv->SetInterpolate (true); value = erv->GetValue (); std::cout << "Interpolated sample:" << value << std::endl; erv->SetInterpolate (false); } void PrintStatsLine (const double value, const long count, const long n) { std::cout << std::fixed << std::setprecision (3) << std::setw (10) << std::right << value << std::setw (10) << std::right << count << std::setw (10) << std::right << count / static_cast (n) * 100.0 << std::endl; } void PrintSummary (long sum, long n, double weighted, double expected) { std::cout << std::endl; std::cout << " --------" << std::endl; std::cout << " Total " << std::setprecision (3) << std::fixed << std::setw (10) << std::right << sum / static_cast (n) * 100.0 << std::endl; std::cout << " Average " << std::setprecision (3) << std::fixed << std::setw (6) << std::right << weighted / n << std::endl; std::cout << " Expected " << std::setprecision (3) << std::fixed << std::setw (6) << std::right << expected << std::endl << std::endl; } void RunBothModes (std::string mode, Ptr erv, long n) { std::cout << std::endl; std::cout << "Sampling " << mode << std::endl; std::map counts; counts[0] = 0; for (long i = 0; i < n; ++i) { ++counts[erv->GetValue ()]; } long sum = 0; double weighted = 0; std::cout << std::endl; std::cout << " Value Counts %" << std::endl; std::cout << "---------- -------- --------" << std::endl; for (auto c : counts) { long count = c.second; double value = c.first; sum += count; weighted += value * count; PrintStatsLine (value, count, n); } PrintSummary (sum, n, weighted, 8.75); std::cout << "Interpolating " << mode << std::endl; erv->SetInterpolate (true); Histogram h (0.5); for (long i = 0; i < n; ++i) { h.AddValue (erv->GetValue ()); // This could also be expressed as // h.AddValue (erv->Interpolate ()); } erv->SetInterpolate (false); sum = 0; weighted = 0; std::cout << std::endl; std::cout << " Bin Start Counts %" << std::endl; std::cout << "---------- -------- --------" << std::endl; for (uint32_t i = 0; i < h.GetNBins (); ++i) { long count = h.GetBinCount (i); double start = h.GetBinStart (i); double value = start + h.GetBinWidth (i) / 2.; sum += count; weighted += count * value; PrintStatsLine (start, count, n); } PrintSummary (sum, n, weighted, 6.25); } int main (int argc, char *argv[]) { long n = 1000000; bool disableAnti = false; bool single = false; CommandLine cmd; cmd.AddValue ("count", "how many draws to make from the rng", n); cmd.AddValue ("antithetic", "disable antithetic sampling", disableAnti); cmd.AddValue ("single", "sample a single time", single); cmd.Parse (argc, argv); std::cout << std::endl; std::cout << cmd.GetName () << std::endl; if (!single) { std::cout << "Sample count: " << n << std::endl; } else { std::cout << "Sampling a single time" << std::endl; } if (disableAnti) { std::cout << "Antithetic sampling disabled" << std::endl; } // Create the ERV in sampling mode Ptr erv = CreateObject (); erv->SetInterpolate (false); erv->CDF ( 0.0, 0.0); erv->CDF ( 5.0, 0.25); erv->CDF (10.0, 1.0); if (single) { RunSingleSample ("normal", erv); if (!disableAnti) { std::cout << std::endl; std::cout << "Antithetic" << std::endl; erv->SetAntithetic (true); RunSingleSample ("antithetic", erv); erv->SetAntithetic (false); } std::cout << std::endl; return 0; } RunBothModes ("normal", erv, n); if (!disableAnti) { erv->SetAntithetic (true); RunBothModes ("antithetic", erv, n); erv->SetAntithetic (false); } return 0; }