Jan 11, 2016
Curso de NS
Rainer R. P. Couto([email protected])
Sumário
Arquitetura do Software Hierarquia de Objetos Principais Classes em OTcl e C++
Escalonador Temporizadores – Timers Geração de números aleatórios
Arquitetura do software
Arquitetura do Software Tcl
“script language” Fracamente tipada Configuração
C/C++ “system language” Fortemente tipada “Core programming”
OTcl Tcl orientado a objetos
TclCL (TclCLass) Tcl com suporte a “object
oriented split-level programming”
Tcl
OTcl
TclCL
ns-2
Esca
lonad
or
de e
ven
tos
Componentesde rede
C/C++
Estrutura Interna
Arquitetura do NS Orientado a objetos Escrito em C++ Interpretador Tcl
como frontend
Arquitetura do NS Duas hierarquias de
objetos Hierarquia C++
(compilada) Hierarquia OTcl
(interpretada) Correspodência um para
um pela perspectiva do usuário
C++ OTcl
Pure C++objects
Pure OTclobjects
C++/OTcl split objects
ns
Split-level programming Por que duas linguagens?
C++: execução rápida / alteração complexa Processamento de cada pacote, alteração de
comportamento de objetos existentes em C++ (“dado”), estruturas e algotirmos complexos, código com alterações infreqüentes
OTcl: alteração simples / execução lenta Configuração, setup, escalonamento de eventos periódicos e
manipulação simples de objetos (“controle”), código com alterações freqüentes
Tclcl provê a forma de unir as duas linguagens
+ Compromisso entre composabilidade e velocidade– Aprendizado e correção de erros
O Mérito do OTcl
Granularidade do código/script pode ser ajustada para compensar extensibilidade por performance.
Tamanho do programacomplexidade
C/C++
OTcl
grande pequeno
split objects
1000
100
10
1
Inst
ruct
ion
s/S
tate
men
t
None Strong Degree of Typing
Assembly C++C
Java
Tcl/Perl
Visual Basic
John Ousterhout. Scripting: Higher-level programming for the 21st centuryIEEE Computer, 1998.
Principais classes da programação C++/OTcl
bind(): realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObjectcommand(): realiza o “link” entre métodos chamados no OTcl e implementados em C++
TclClass Cria e inicializa TclObject’s
Tcl Métodos C++ para acessar o interpretador Tcl
TclCommand Comandos globais
EmbeddedTcl Inicialização do script ns
Raiz da hierarquia de objetos do ns-2
Principais classes da programação C++/OTcl
bind(): realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObjectcommand(): realiza o “link” entre métodos chamados no OTcl e implementados em C++
TclClass Cria e inicializa TclObject’s
Tcl Métodos C++ para acessar o interpretador Tcl
TclCommand Comandos globais
EmbeddedTcl Inicialização do script ns
Raiz da hierarquia de objetos do ns-2
TclObject: Hierarquia e Shadowing
TclObject
Agent
Agent/TCP
Agent/TCP OTcl Objeto shadow
_o123Objeto
Agent/TCP C++
*tcp
TclObject
Agent
TcpAgent
Hierarquia declasses OTcl
Hierarquia declasses C++
TclObject::bind() “Une” variáveis membras de classes no C++ a variáveis
no OTcl Duas referências para um mesmo objeto
C++TcpAgent::TcpAgent() {TcpAgent::TcpAgent() {
bind(“bind(“window_window_”, &wnd_);”, &wnd_);bind_bw(“bind_bw(“taxataxa__", &", &taxataxa_);_);
}} bind_time(), bind_bool(), bind_bw()
OTclset tcp [new Agent/TCP]set tcp [new Agent/TCP]$tcp set window_ 200$tcp set window_ 200$tcp set taxa_ 1.5Mb$tcp set taxa_ 1.5Mb
Inicialização de variáveis do “bind”
Inicialização através de variáveis de classe do OTclAgent/TCP set Agent/TCP set window_window_ 50 50
Faça toda a inicialização de variáveis de “bind” em ~ns/tcl/lib/ns-default.tcl
Caso contrário, um aviso de alerta será mostrado quando o objeto “shadow” for criado
Implementação de variáveis de “bind”
Classe InstVar Um objeto por variável de “bind” – caro! InstVarInt, InstVarReal, ...
Criados por TclObject::bind() Cria instância da variável na pilha OTcl Habilita “trap” de escrita/leitura para variável OTcl Conecta à variável C++ na ocorrência de “traps”
TclObject::command()
Implementa métodos do OTcl em C++ “Trap point”: Método cmd{} em OTcl
Após chamado, cmd{} envia todos seus argumentos para TclObject::command()
TclObject::command() OTcl
set tcp [new Agent/TCP]$tcp advance 10
C++int TcpAgent::command(int argc,
const char*const* argv) { if (argc == 3) {
if (strcmp(argv[1], “advance”) == 0) { int newseq = atoi(argv[2]);
…… return(TCL_OK);
} }
return (Agent::command(argc, argv);}
TclObject::command()
$tcp send TclObject::unknown{} $tcp cmd sendprocedimentonão existe
TcpAgent::command()
implementa “send”?
Chama o método do pai: return Agent::command()
Processa e retorna
Sim Não
OTcl space
C++ space
TclObject: Criação e Remoção
Procedimentos globais: new{}, delete{} Exemplo
set tcp [set tcp [newnew Agent/TCP] Agent/TCP]
……
deletedelete $tcp $tcp
TclObject: Criação e Remoção
C++
OTcl
chama cons_trutor do pai
construtorAgent/TCP
construtorpai (Agent)
chama cons_trutor do pai
construtorTclObject
cria objeto C++
construtorAgentTCP
chama cons_trutor do pai
chama cons_trutor do pai
construtor pai (Agent)
Não faz nada,retorna
construtorTclObject (C++)
realiza bindse retorna
realiza bindse retorna
cria objeto shadow OTcl
completainicialização
completainicialização
Qual objeto C++deve ser criado? – TclClass
Principais classes da programação C++/OTcl
TclClass Cria e inicializa TclObject’s
Tcl Métodos C++ para acessar o interpretador Tcl
TclCommand Comandos globais
EmbeddedTcl Inicialização do script ns
bind(): realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObjectcommand(): realiza o “link” entre métodos chamados no OTcl e implementados em C++
Raiz da hierarquia de objetos do ns-2
TclClass
TclObject
Agent
Agent/TCP
TclObject
Agent
TcpAgent
NsObject ??
OTclC++ Static class TcpClass : public TclClass {public:
TcpClass() : TclClass(“Agent/TCP”) {}TclObject* create(int, const char*const*) {
return (new TcpAgent());}
} class_tcp;
Static class TcpClass : public TclClass {public:
TcpClass() : TclClass(“Agent/TCP”) {}TclObject* create(int, const char*const*) {
return (new TcpAgent());}
} class_tcp;
TclClass: Mecanismo
Inicialização durante o “startup” da execução
SplitObject::register{} Cria e registra
Classe OTcl Agent/TCP
TclClass::init()
para cada TclClassdefinida estaticamente
TcpClass::bind()
e.g.
Agent/TCP::create-shadow{} TclClass::create_shadow()
Principais classes da programação C++/OTcl
bind(): realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObjectcommand(): realiza o “link” entre métodos chamados no OTcl e implementados em C++
TclClass Cria e inicializa TclObject’s
Tcl Métodos C++ para acessar o interpretador Tcl
TclCommand Comandos globais
EmbeddedTcl Inicialização do script ns
Raiz da hierarquia de objetos do ns-2
Classe Tcl
Classe que possui a referência para o interpretador Tcl
Uso Chamar procedimentos em OTcl Obter resultados de expressões em OTcl Passar um resultado para o OTcl Retornar um código de sucesso/falha para o Otcl Armazenar e realizar procuras por referências a
TclObjects
Obtendo uma referência para o interpretador
Uma única referência ao intepretador está declarado no arquivo Tcl.cc (dentro do diretório tclclXXX) como um membro estático da classe Tcl. Antes de acessar qualquer método do intepretador, devemos obter essa referência.
Comando
Tcl& tcl = Tcl::instance();Tcl& tcl = Tcl::instance();
Passandos comandos para o interpretador
Tcl& tcl = Tcl::instance(); Tcl& tcl = Tcl::instance();
char wrk[128];char wrk[128];
strcpy(wrk, "Simulator set NumberInterfaces_ 1"); strcpy(wrk, "Simulator set NumberInterfaces_ 1");
tcl.eval(wrk); tcl.eval(wrk);
sprintf(tcl.buffer(), "Agent/SRM set requestFunction_ %s",sprintf(tcl.buffer(), "Agent/SRM set requestFunction_ %s", "Fixed"); "Fixed");
tcl.eval(); tcl.eval();
tcl.evalc("puts stdout tcl.evalc("puts stdout \”\”hello worldhello world\”\”"); ");
tcl.evalf("%s request %d %d", name_, sender, msgid); tcl.evalf("%s request %d %d", name_, sender, msgid);
Tcl::eval(char *): passa string para o intepretador Tcl::evalc(const char *): preserva o string de entrada Tcl::eval(): supõe que o comando já está em tcl.buffer Tcl::evalf(char *, par1, par2, ...): “printf like” Exemplo:
Coletando resultados
Quanto o intepretador chama um comando em C++, espera-se um resultado na variável interna result.
Comando: tcl.resultf()
Similarmente, quando o C++ faz uma chamada a um método do interpretador, o resultado pode ser acessado através da mesma variável.
Comando: tcl.result()
Exemplo de métodos de Tcl
Tcl& tcl = Tcl::instance();if (argc == 2) {
if (strcmp(argv[1], “now”) == 0) {tcl.resultf(“%g”, clock());return TCL_OK;
}tcl.error(“command not found”);return TCL_ERROR;
} else if (argc == 3) {tcl.eval(argv[2]);clock_ = atof(tcl.result());return TCL_OK;
}
Funções de Hash da classe Tcl
O intepretador possui uma tabela hash com entradas para todos TclObjects criados durante a simulação.
void Tcl::enter(TclObject* o) Utilizado para criar uma nova entrada para o novo
TclObject
TclObject* Tcl::lookup(const char* name) Utilizado para fazer uma procura por um TclObject
Principais classes da programação C++/OTcl
bind(): realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObjectcommand(): realiza o “link” entre métodos chamados no OTcl e implementados em C++
TclClass Cria e inicializa TclObject’s
Tcl Métodos C++ para acessar o interpretador Tcl
TclCommand Comandos globais
EmbeddedTcl Inicialização do script ns
Raiz da hierarquia de objetos do ns-2
Class TclCommand Implementação em C++ de comandos globais em OTcl
class RandomCommand : public TclCommand {public: RandomCommand() : TclCommand("ns-random") {} virtual int command(int argc, const char*const* argv);};
int RandomCommand::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 1) { ... }} Inicializar um novo objeto – new RandomCommand() – em
misc.cc::init_misc
Principais classes da programação C++/OTcl
bind(): realiza o “link” dos valores das variáveis compartilhadas entre C++ e OTcl TclObjectcommand(): realiza o “link” entre métodos chamados no OTcl e implementados em C++
TclClass Cria e inicializa TclObject’s
Tcl Métodos C++ para acessar o interpretador Tcl
TclCommand Comandos globais
EmbeddedTcl Inicialização do script ns
Raiz da hierarquia de objetos do ns-2
EmbeddedTcl Carrega OTcl scripts durante a inicialização do ns
Carrega recursivamente ~ns/tcl/lib/ns-lib.tcl:~ns/tcl/lib/ns-lib.tcl:source ns-autoconf.tclsource ns-autoconf.tclsource ns-address.tclsource ns-address.tclsource ns-node.tclsource ns-node.tcl....... .......
Carrega tudo em um único vetor de caracteres em C++ Executa esse string durante a inicialização
EmbeddedTcl
Como funciona tcl2c++tcl2c++: provido pelo TclCL, converte tcl scripts em
vetores estáticos de caracteres em C++ Makefile.in:
tclsh8.0 bin/tcl-expand.tcl tcl/lib/ns-lib.tcl tclsh8.0 bin/tcl-expand.tcl tcl/lib/ns-lib.tcl | tcl2c++ et_ns_lib > gen/ns_tcl.cc| tcl2c++ et_ns_lib > gen/ns_tcl.cc
Resumo TclObject
Classe raiz das hierarquias compilada (C++) e interpretada (OTcl)
Acesso transparente (chamadas de procedimento e acesso de variáveis) entre OTcl e C++
TclClass Mecanismo que torna possível TclObject
Tcl Primitivas para acessar o interpretador Tcl
Escalonador
Utilizando-se o NS... Criação do simulador
Escalonador de eventos
[Habilitação do tracing] Criação da rede Configuração do roteamento ...
set ns [new Simulator]set ns [new Simulator]
# [Turn on tracing]# [Turn on tracing]
# Create topology# Create topology
# Setup packet loss, link # Setup packet loss, link dynamicsdynamics
# Create routing agents# Create routing agents
# Create: # Create:
# - multicast groups# - multicast groups
# - protocol agents# - protocol agents
# - application and/or setup # - application and/or setup traffic sourcestraffic sources
# Post-processing procs# Post-processing procs
# Start simulation# Start simulation
Escalonador
O que é o escalonador? Controlador de eventos dentro do simulador
Arquivos correspondentes: tcl/lib/ns-lib.tcl (class Simulator) common/scheduler(.h,.cc) (class Scheduler) heap.h (class Heap)
Modelo do escalonador
Modela mundo como eventos Simulador possui uma lista de eventos Processo: pega o primeiro evento da lista, executa
até estar completo Cada evento acontece em um determinado instante
do tempo virtual (tempo simulado), mas pode levar um tempo real arbitrátio
Implementação muito simples uma thread de controle => não precisamos nos
preocupar com condições de corrida ou “locking” (bem simples)
Escalonador de Eventos
time_, uid_, next_, handler_
handler_ -> handle()
time_, uid_, next_, handler_insert
head_ ->
class Event {public: Event* next_; /* event list */ Handler* handler_; /* handler to call when event ready */ double time_; /* time at which event is ready */ scheduler_uid_t uid_; /* unique ID */ Event() : time_(0), uid_(0) {}};
class Handler { public: virtual void handle(Event* event) = 0;};
Modelo do escalonador
Considere dois nodosem uma rede Ethernet
A B
Modelo de filas simplificado:t=1 A coloca um pacote na fila da LANt=1.01 LAN retira o pacote da fila e LAN e
dispara um evento de recepção em B
Modelo CSMA/CD detalhado:
t=1.0 A envia pacote para NIC; NIC de A inicia “carrier sense”
t=1.005 NIC de A conclui cs, inicia txt=1.006 NIC de B começa a recepção do pacotet=1.01 NIC de B conclui recepção do pacote
NIC de B passa pacote para agente/aplicação
Criação do escalonador Criação do simulador de eventos
set ns [new Simulator] Escalonamento de eventos
$ns at <tempo> <evento> <evento>: qualquer comando legítimo no ns/tcl Ex: $ns at 5.0 “finish”
Início da execução do escalonador$ns run
Escalonador Calendar: default Escalonador Real-time
Sincroniza com tempo real Emulação de redes
set ns_ [new Simulator]set ns_ [new Simulator]$ns_ use-scheduler Heap$ns_ use-scheduler Heap$ns_ at 300.5 “$self halt”$ns_ at 300.5 “$self halt”
Simulador - métodosSimulator instproc init args {Simulator instproc init args {
$self instvar useasim_$self instvar useasim_
......__
set slinks_(0:0) 0set slinks_(0:0) 0
......
$self create_packetformat$self create_packetformat
$self use-scheduler Calendar$self use-scheduler Calendar
#$self use-scheduler List#$self use-scheduler List
......
}}
Simulator instproc use-scheduler type {Simulator instproc use-scheduler type {
$self instvar scheduler_$self instvar scheduler_
if [info exists scheduler_] {if [info exists scheduler_] {
if { [$scheduler_if { [$scheduler_ info class] == info class] ==
"Scheduler/$type" } {"Scheduler/$type" } {
returnreturn
} else {} else {
delete $scheduler_delete $scheduler_
}}
}}
set scheduler_ [newset scheduler_ [new Scheduler/$type]Scheduler/$type]
$scheduler_$scheduler_ nownow
}}Simulator instproc at args {Simulator instproc at args {
$self instvar scheduler_$self instvar scheduler_
return [eval $scheduler_ at $args]return [eval $scheduler_ at $args]
}}
Simulator instproc run {} {Simulator instproc run {} {
......
return [$scheduler_ run]return [$scheduler_ run]
}}
Escalonador - Tipos
ListScheduler Lista simples O(N)
HeapScheduler Baseado em um
Heap O(logN)
CalendarScheduler Baseado em Hash
O(1) SplayScheduler RealTimerScheduler
Modos do escalonadorModo interativo
arara:/ns-> ns
% set ns [new Simulator]
_o3
% $ns at 1 “puts \“Hello World!\””
1
% $ns at 1.5 “exit”
2
% $ns run
Hello World!
arara:/ns->
Modo batch:
simple.tcl
set ns [new Simulator]
$ns at 1 “puts \“Hello World!\””
$ns at 1.5 “exit”
$ns run
arara:/ns-> ns simple.tcl
Hello World!
arara:/ns->
Temporizadores – Timers
Temporizadores – Timers O que é um temporizador?
Um temporizador (timer) é um elemento que dispara um determinado evento e que pode ser programado
Usado principalmente em agentes, mas pode ser utilizado em outros objetos
Ex: retransmissão no agente TCP
Temporizadores podem ser implementados em C++ ou em OTcl.
São baseados em uma classe abstrata definida em timer-handler.h
Em OTcl um temporizador pode ser criado derivando a classe definida em tcl/mcast/timer.tcl.
Temporizadores – Funções e atributos
A classe abstrata TimerHandler contém os seguintes métodos públicos disponíveis:
void sched(double delay) Escalona um temporizador para disparar em “delay”
segundos void resched(double delay)
Re-escalona o temporizador (similar ao sched, mas o temporizador pode estar pendente)
void cancel() Cancela um temporizador pendente
int status() Retorna o status do temporizador (TIMER_IDLE,
TIMER_PENDING, ou TIMER_HANDLING)
Temporizadores – Funções e atributos
A classe abstrata TimerHandler contém os seguintes métodos protegidos disponíveis:
virtual void expire (Event* e) = 0 Este método deve ser preenchido com o código a ser
executado no instante de disparo do evento virtual void handle (Event* e)
Consome um evento; faz um chamada para expire() e atribui o valor adequado a status_
int status_ Variável que mantém o atual status do temporizador
Event event_ Evento que deve ser consumido
Temporizadores – Funções e atributos
O método virtual expire() deve ser defindo na classe derivada da classe abstrata
Dois métodos privados “inline” são definidos: inline void _sched(double delay)
{ (void)Scheduler::instance().schedule(this, &event_, delay); }
inline void _cancel() { (void)Scheduler::instance().cancel(&event_); }
Esses códigos utilizam diretamente métodos do escalonador.
Definindo um Temporizador
Temporizadores criados em C++ não são diretamente acessíveis através do Otcl.
Geralmente um temporizador será uma classe amiga da classe agente onde se encontra ou expire() chamará um método público deste agente.
class MyTimer : public TimerHandler { public: MyTimer(MyAgentClass *a) : TimerHandler() { a_ = a; } virtual double expire(Event *e); protected: MyAgentClass *a_; };
double MyTimer::expire(Event *e) {
// executa a função // Opção 1: // =\> não re-escalona o temporizador // Opção 2: // =\> re-escalona temporizador para // =\> disparar novamente em “delay” // =\> segundos }
Exemplo – Retransmissão no TCP
Existem três temporizadores declarados no agente TCP Tahoe definido em tcp.cc:
rtx_timer_; Temporizador de retransmissão
delsnd_timer_; Atrasa o envio do pacote por um pequeno tempo aleatório, de
forma a evitar efeitos cíclicos burstsnd_timer_;
Auxilia o TCP no envio de uma grande janela de tranmissão dividida em várias partes menores
Em tcp.h existem três classes de temporizadores definidas:
class RtxTimer class DelSndTimer class BurstSndTimer
class RtxTimer : public TimerHandler { public: RtxTimer(TcpAgent *a) : TimerHandler() { a_ = a; } protected: virtual void expire(Event *e); TcpAgent *a_; };
Exemplo – Retransmissão no TCP
TcpAgent::TcpAgent() : Agent(PT_TCP), rtt_active_(0), rtt_seq_(-1), ... rtx_timer_(this), delsnd_timer_(this), burstsnd_timer_(this) { ... }
void TcpAgent::set_rtx_timer() { rtx_timer_.resched(rtt_timeout()); }
void TcpAgent::newtimer (Packet* pkt) { hdr_tcp *tcph = (hdr_tcp*) pkt->access( off_tcp_ ); if ( t_seqno_ > tcph->seqno() ) set_rtx_timer(); else if ( rtx_timer_.status() == TIMER_PENDING ) rtx_timer_.cancel(); }
void TcpAgent::timeout( int tno ) { ... }
void RtxTimer::expire( Event *e ) { a_->timeout( TCP_TIMER_RTX ); }
Temporizador em OTcl
Diferença básica: ao contrário da implementação em C++, onde uma chamada a sched() para um temporizador pendente causa um abort(), sched e resched em OTcl possuem a mesma funcionalidade
Nenhum estado é mantido para o temporizador
As seguintes funções são definidas para o temporizador: $self sched $delay # programa o temporizador para $delay
seg.; $self resched $delay # o memo que "$self sched $delay" ; $self cancel # cancela o temporizador (não há callback); $self destroy # o mesmo que "$self cancel"; $self expire # faz uma chamada a "$self timeout"
imediatamente; “timeout” deve estar definida na subclasse
/tcl/mcast/timer.tcl:...Timer instproc sched delay { $self instvar ns_ $self instvar id_ $self cancel set id_ [$ns_ after $delay "$self timeout"]}...
Geração de Números Aleatórios
Geração de Números Aleatórios
Suporte Matemático. O NS possui uma pequena coleção de funções
matemáticas usadas para implementar funções geradoras de números aleatórios e cálculos de integrais.
Os procedimentos podem ser encontrados nos seguintes arquivos:
tools/rng.{cc, h}. tools/random.{cc, h}. tools/ranvar.{cc, h}. tools/pareto.{cc, h}. tools/expoo.{cc, h}. tools/integrator.{cc, h}. tcl/lib/ns-random.tcl.
Geração de números aleatórios
A classe RNG possui a implementação de um gerador recursivo-múltiplo-combinado de números aleatórios (combined multiple recursive random number generator), ou MRG32k3a, proposto por L'Ecuyer (para versões 2.1b9 e posteriores).
Versões anteriores utilizam o minimal standard multiplicative linear congruential generator, proposto por Park and Miller
O gerador MRG32k3a provê 1,8x1019 streams independentes de números aleatórios, cada streams sendo composto por 2,3x1015 substreams.
Cada substream possui um período de 7,6x1022
O período do gerador é de 3,1x1057
Pierre L'Ecuyer. Good parameters and implementations for combined multiple recursive random number generators. Operations Research, 1999
S.K. Park and R.W. Miller. Random number generation: Good ones are hard to find. Communications of the ACM, 1988.
Geração de números aleatórios
Um gerador RNG default é criado no início da simulação (defaultRNG).
Se múltiplas variáveis aleatórias são utilizadas durante uma simulação, cada variável deve utilizar um objeto RNG distinto.
Quando uma nova variável RNG é criada, à sua semente é atribuído um valor de modo a gerar o próximo stream independente de números aleatórios.
A implementação permite um número máximo de 1,8x1019 var. aleatórias.
Geralmente são necessárias várias réplicas de um mesmo experimento (análise estatística)
Para cada réplica, um substream diferente deve ser utilizado para garantir que as seqüências de números aleatórios sejam independentes.
Esse processo limita o número de réplicas possíveis em, no máximo, 2,3x1015.
Pierre L'Ecuyer, Richard Simard, E. Jack Chen, and W. David Kelton. An object-oriented random number package with many long streams and substreams. Operations Research, 2001.
E também em:tools/rng.htools/rng.cc
Semente Semente default de defaultRNG: 12345
Somente a semente de defaultRNG necessita ser inicializada Cada RNG é inicializado de modo a produzir uma seqüência
independente de números. A semente pode ser inicializada com qualquer valor entre 1 e
MAXINT (2147483647).
Para obter comportamento não-determinístico, basta inicializar a semente para 0.
A nova semente é baseada na hora corrente e em um contador.
Não deve ser usado para produzir uma seqüência independente de dados, já que não há garantia que as seqüências não irão se sobrepor.
A única forma de garantir que duas seqüências não irão se sobrepor é utilizar substreams.
Exemplo 1 - script# Usage: ns rng-test.tcl [replication number]
if {$argc > 1} {
puts "Usage: ns rng-test.tcl \[replication number\]"
exit
}
set run 1
if { $argc == 1 } { set run [lindex $argv 0] }
if { $run < 1 } { set run 1 }
$sizeRNG next-substream
}
# seed the default RNG
global defaultRNG
$defaultRNG seed 9999
# create the RNGs and set them to the correct substream
set arrivalRNG [new RNG]
set sizeRNG [new RNG]
for {set j 1} {$j < $run} {incr j} {
$arrivalRNG next-substream
# arrival_ is a exponential random variable describing the time
# between consecutive packet arrivals
set arrival_ [new RandomVariable/Exponential]
$arrival_ set avg_ 5
$arrival_ use-rng $arrivalRNG # size_ is a uniform random variable describing packet sizes
set size_ [new RandomVariable/Uniform]
$size_ set min_ 100
$size_ set max_ 5000
$size_ use-rng $sizeRNG # print the first 5 arrival times and sizes
for {set j 0} {$j < 5} {incr j} {
puts [ format "%-8.3f %-4d" [ $arrival_ value ] \
[expr round([$size_ value])]]
}
Exemplo 1 - script# Usage: ns rng-test.tcl [replication number]
if {$argc > 1} {
puts "Usage: ns rng-test.tcl \[replication number\]"
exit
}
set run 1
if { $argc == 1 } { set run [lindex $argv 0] }
if { $run < 1 } { set run 1 } # seed the default RNG
global defaultRNG
$defaultRNG seed 9999
$sizeRNG next-substream
}
# create the RNGs and set them to the correct substream
set arrivalRNG [new RNG]
set sizeRNG [new RNG]
for {set j 1} {$j < $run} {incr j} {
$arrivalRNG next-substream
# arrival_ is a exponential random variable describing the time
# between consecutive packet arrivals
set arrival_ [new RandomVariable/Exponential]
$arrival_ set avg_ 5
$arrival_ use-rng $arrivalRNG # size_ is a uniform random variable describing packet sizes
set size_ [new RandomVariable/Uniform]
$size_ set min_ 100
$size_ set max_ 5000
$size_ use-rng $sizeRNG # print the first 5 arrival times and sizes
for {set j 0} {$j < 5} {incr j} {
puts [ format "%-8.3f %-4d" [ $arrival_ value ] \
[expr round([$size_ value])]]
}
Exemplo - saída
% ns rng-test.tcl 1
6.358 4783 5.828 1732 1.469 2188 0.732 3076 4.002 626
% ns rng-test.tcl 5
0.691 1187 0.204 4924 8.849 857 2.111 4505 3.200 1143
Comandos OTcl Os seguintes comandos do RNG podem ser acessados
através do OTcl e se encontram implementados em tools/rng.cc:
seed <raiz>: atribui o parâmetro à raiz do gerador. O valor 0 indica uma raiz baseada na hora corrente e em um contador
next-random: retorna próximo número aleatório seed: retorna o valor da raiz next-substream: avança para o próximo reset-start-substream: reinicia o substream para o início da
seqüência de números aleatórios normal <avg> <stddev>: retorna um número aleatório de
uma distribuição normal segundo os parâmetros de entrada lognormal <avg> <stddev>: retorna um número aleatório
de uma distribuição lognormal segundo os parâmetros de entrada.
Comandos OTcl
Os seguintes comandos do RNG podem ser acessados através do OTcl e se encontram implementados em tcl/lib/ns-random.tcl:
exponential <mean>: retorna um número aleatório retirado de uma distribuição exponencial segundo o parâmetro de entrada
uniform <a> <b>: retorna um inteiro retirado de uma distribuição uniforme no intervalo [a , b]
integer <k>: retorna um inteiro retirado de uma distribuição uniforme no intervalo [0 , k-1]
Exemplo 2 - script# Usage: ns rng-test2.tcl [replication number]
if { $argc > 1 } {
puts "Usage: ns rng-test2.tcl \[replication number\]"
exit
}
set run 1
if { $argc == 1 } { set run [lindex $argv 0] }
if { $run < 1 } { set run 1 } # the default RNG is seeded with 12345
# create the RNGs and set them to the correct substream
set arrivalRNG [new RNG]
set sizeRNG [new RNG]
for { set j 1 } { $j < $run } { incr j } {
$arrivalRNG next-substream
$sizeRNG next-substream
}
# print the first 5 arrival times and sizes
for { set j 0 } { $j < 5 } { incr j } {
puts [format "%-8.3f %-4d" [$arrivalRNG lognormal 5 0.1] \
[expr round([$sizeRNG normal 5000 100])]] }
Saída % ns rng-test2.tcl 1142.776 5038 174.365 5024 147.160 4984 169.693 4981 187.972 4982
Saída % ns rng-test2.tcl 5160.993 4907 119.895 4956 149.468 5131 137.678 4985 158.936 4871
Comandos C++ Métodos da classe RNG
O gerador de números aleatórios está implementado na classe RNGImplementation dentro de tools/rng(.h,.cc).
Note: A classe Random em tools/random.h é uma interface para a classe RNG (compatibilidade com versões anteriores)
Classe RNGImplementation: void set_seed (long seed): igual a OTcl long seed (void): retorna o valor da semente long next (void): próximo número entre [0,MAXINT] double next_double (void) próximo número entre [0,1] void reset_start_substream (void): reinicia substream void reset_next_substream (void): próximo substream
Comandos C++ Métodos da classe RNG
Classe RNGImplementation:
int uniform (int k): retorna inteiro da dist. uniforme entre [0,k-1] double uniform (double r): dist. uniforme entre [0, r] double uniform (double a, double b): dist. uniforme entre [a,b] double exponential (void): dist. exponencial com valor médio 1.0 double exponential (double k): dist. exponencial com valor médio
k double normal (double avg, double std): dist. normal com média
e desvio padrões dados double lognormal (double avg, double std): dist. lognormal com
média e desvio padrões dados
Exemplo - código
/* create new RNGs */ RNG arrival (23456); RNG size; Saída
161.826 506160.591 503 157.145 509 137.715 507 118.573 496
/* set the RNGs to the appropriate substream */ for (int i = 1; i < 3; i++) { arrival.reset_next_substream(); size.reset_next_substream(); }
/* print the first 5 arrival times and sizes */ for (int j = 0; j < 5; j++) { printf ("%-8.3f %-4d\n", arrival.lognormal(5, 0.1), int(size.normal(500, 10))); }
Variáveis Aleatórias A classe RandomVariable provê uma abstração
das funcionalidades do gerador de números aleatórios e da seqüência de números gerados.
Arquivos: tools/ranvar(.h,.cc)
class RandomVariable : public TclObject { public: virtual double value() = 0; int command(int argc, const char*const* argv); RandomVariable(); protected: RNG* rng_; };
Classes que derivam dessa classe abstrata
implementam uma distribuição específica.
Cada distribuição é parametrizada com os respectivos valores. O método virtual value é
utilizado para retornar um número que segue a
distribuição implementada.
Variáveis Aleatórias
As distribuições implementadas na versão atual e seus parâmetros são:
UniformRandomVariable: min_, max_ ExponentialRandomVariable: avg_ ParetoRandomVariable: avg_, shape_ ParetoIIRandomVariable: avg_, shape_ ConstantRandomVariable: val_ HyperExponentialRandomVariable: avg_, cov_ NormalRandomVariable: avg_, std_ LogNormalRandomVariable: avg_, std_
Variáveis Aleatórias
A classe RandomVariable está disponível em OTcl.
Exemplo: criar uma variável randômica que gera números aleatórios uniformemente distribuídos no intervalor [10, 20] set u [new set u [new
RandomVariable/Uniform]RandomVariable/Uniform]
$u set min_ 10 $u set min_ 10
$u set max_ 20 $u set max_ 20
$u value$u value Por default, um objeto RandomVariable utiliza
o RNG default do NS. Para associar um novo RNG à variável deve-se utilizar o método use-rng.
set rng [new RNG]set rng [new RNG]
$rng seed 0 $rng seed 0
set e [newset e [new
RandomVariable/Exponential] RandomVariable/Exponential]
$e use-rng $rng$e use-rng $rng
Integrais
Ns possui uma classe para cálculos de integrais nos arquivos tools/integrator(.h,.cc)
Aproximação da integral contínua através de somas discretas
class Integrator : public TclObject { public: Integrator(); void set(double x, double y); void newPoint(double x, double y); int command(int argc, const char*const* argv);protected: double lastx_; double lasty_; double sum_; };