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





“system language”
Fortemente tipada
“Core programming”
OTcl


TclCL
C/C++


Componentes
de rede
Tcl
C/C++
Tcl orientado a objetos
TclCL (TclCLass)

OTcl
Tcl com suporte a “object
oriented split-level
programming”
ns-2
Escalonador
de eventos

“script language”
Fracamente tipada
Configuração
Estrutura Interna

Arquitetura do NS




Orientado a objetos
Escrito em C++
Interpretador Tcl como
Arquitetura do NS




frontend
Hierarquia C++ (compilada)
Hierarquia OTcl (interpretada)
Correspodência um para um
pela perspectiva do usuário
Pure OTcl
objects
Pure C++
objects
C++
Duas hierarquias de objetos
C++/OTcl split
objects
ns
OTcl
Split-level programming

Por que duas linguagens?

C++: execução rápida / alteração complexa


OTcl: alteração simples / execução lenta


+
–
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
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
grande
Tamanho do programa
complexidade
C/C++
pequeno
OTcl
split
objects
Instructions/Statement
O Mérito do OTcl
1000
Visual
Basic
100
Tcl/Perl
10
Java
Assembly
1
None

Granularidade do código/script
pode ser ajustada para compensar
extensibilidade por performance.
C
C++
Degree of Typing
John Ousterhout.
Scripting: Higher-level
programming for the 21st
century
IEEE Computer, 1998.
Strong
Principais classes da
programação C++/OTcl
Raiz da hierarquia de objetos do ns-2
TclObject
TclClass
Tcl
bind(): realiza o “link” dos valores das
variáveis compartilhadas entre C++ e OTcl
command(): realiza o “link” entre métodos
chamados no OTcl e implementados em C++
Cria e inicializa TclObject’s
Métodos C++ para acessar o interpretador Tcl
TclCommand
Comandos globais
EmbeddedTcl
Inicialização do script ns
Principais classes da
programação C++/OTcl
Raiz da hierarquia de objetos do ns-2
TclObject
TclClass
Tcl
bind(): realiza o “link” dos valores das
variáveis compartilhadas entre C++ e OTcl
command(): realiza o “link” entre métodos
chamados no OTcl e implementados em C++
Cria e inicializa TclObject’s
Métodos C++ para acessar o interpretador Tcl
TclCommand
Comandos globais
EmbeddedTcl
Inicialização do script ns
TclObject: Hierarquia e Shadowing
TclObject Hierarquia de
classes OTcl
Hierarquia de TclObject
classes C++
Agent
Agent
Agent/TCP
TcpAgent
_o123
Agent/TCP OTcl
Objeto shadow
*tcp
Objeto
Agent/TCP 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() {
bind(“window_”, &wnd_);
bind_bw(“taxa_", &taxa_);
}


bind_time(), bind_bool(), bind_bw()
OTcl
set tcp [new Agent/TCP]
$tcp set window_ 200
$tcp set taxa_ 1.5Mb
Inicialização de variáveis do
“bind”

Inicialização através de variáveis de classe do OTcl
Agent/TCP set window_ 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 procedimento
não existe
OTcl space
TclObject::unknown{}
C++ space
TcpAgent::command()
Sim
Processa e retorna
implementa
“send”?
$tcp cmd send
Não
Chama o método do pai:
return Agent::command()
TclObject: Criação e Remoção


Procedimentos globais: new{}, delete{}
Exemplo
set tcp [new Agent/TCP]
…
delete $tcp
TclObject: Criação e Remoção
construtor
Agent/TCP
chama cons_
trutor do pai
completa
inicialização
construtor
pai (Agent)
chama cons_
trutor do pai
completa
Qual
objeto C++
inicialização
deve
ser criado?
construtor
TclObject
cria objeto
C++
cria objeto
shadow OTcl
– TclClass
construtor
TclObject (C++)
construtor
pai (Agent)
construtor
AgentTCP
Não faz nada,
retorna
chama cons_
trutor do pai
realiza binds
e retorna
chama cons_
trutor do pai
realiza binds
e retorna
OTcl
C++
Principais classes da
programação C++/OTcl
Raiz da hierarquia de objetos do ns-2
TclObject
TclClass
Tcl
bind(): realiza o “link” dos valores das
variáveis compartilhadas entre C++ e OTcl
command(): realiza o “link” entre métodos
chamados no OTcl e implementados em C++
Cria e inicializa TclObject’s
Métodos C++ para acessar o interpretador Tcl
TclCommand
Comandos globais
EmbeddedTcl
Inicialização do script ns
TclClass
C++
TclObject
NsObject
Agent
TcpAgent
Static class TcpClass
OTcl : public TclClass {
public:
TcpClass()
: TclClass(“Agent/TCP”) {}
TclObject
TclObject* create(int, const char*const*) {
return (new TcpAgent());
??
}
} class_tcp;
Agent
Agent/TCP
TclClass: Mecanismo

Inicialização durante o “startup” da execução
TcpClass::bind()
TclClass::init()
para cada TclClass
definida estaticamente
e.g.
SplitObject::register{}
Cria e registra
Classe OTcl Agent/TCP
Agent/TCP::create-shadow{}
TclClass::create_shadow()
Principais classes da
programação C++/OTcl
Raiz da hierarquia de objetos do ns-2
TclObject
TclClass
Tcl
bind(): realiza o “link” dos valores das
variáveis compartilhadas entre C++ e OTcl
command(): realiza o “link” entre métodos
chamados no OTcl e implementados em C++
Cria e inicializa TclObject’s
Métodos C++ para acessar o interpretador Tcl
TclCommand
Comandos globais
EmbeddedTcl
Inicialização do script ns
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();
Passandos comandos para o
interpretador

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:



Tcl& tcl = Tcl::instance();
char wrk[128];
strcpy(wrk, "Simulator set NumberInterfaces_ 1");
tcl.eval(wrk);
sprintf(tcl.buffer(), "Agent/SRM set requestFunction_ %s", "Fixed");
tcl.eval();
tcl.evalc("puts stdout \”hello world\”");
tcl.evalf("%s request %d %d", name_, sender, msgid);
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
Raiz da hierarquia de objetos do ns-2
TclObject
TclClass
Tcl
bind(): realiza o “link” dos valores das
variáveis compartilhadas entre C++ e OTcl
command(): realiza o “link” entre métodos
chamados no OTcl e implementados em C++
Cria e inicializa TclObject’s
Métodos C++ para acessar o interpretador Tcl
TclCommand
Comandos globais
EmbeddedTcl
Inicialização do script ns
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
Raiz da hierarquia de objetos do ns-2
TclObject
TclClass
Tcl
bind(): realiza o “link” dos valores das
variáveis compartilhadas entre C++ e OTcl
command(): realiza o “link” entre métodos
chamados no OTcl e implementados em C++
Cria e inicializa TclObject’s
Métodos C++ para acessar o interpretador Tcl
TclCommand
Comandos globais
EmbeddedTcl
Inicialização do script ns
EmbeddedTcl

Carrega OTcl scripts durante a inicialização do ns

Carrega recursivamente ~ns/tcl/lib/ns-lib.tcl:
source ns-autoconf.tcl
source ns-address.tcl
source ns-node.tcl
.......


Carrega tudo em um único vetor de caracteres em C++
Executa esse string durante a inicialização
EmbeddedTcl

Como funciona
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
| tcl2c++ et_ns_lib > gen/ns_tcl.cc

Resumo

TclObject



TclClass


Classe raiz das hierarquias compilada (C++) e interpretada
(OTcl)
Acesso transparente (chamadas de procedimento e acesso
de variáveis) entre OTcl e C++
Mecanismo que torna possível TclObject
Tcl

Primitivas para acessar o interpretador Tcl
Escalonador
Utilizando-se o NS...

Criação do simulador





set ns [new Simulator]
Escalonador de eventos
[Habilitação do tracing]
Criação da rede
Configuração do roteamento
...
# [Turn on tracing]
# Create topology
# Setup packet loss, link
dynamics
# Create routing agents
# Create:
#
- multicast groups
#
- protocol agents
#
- application and/or setup
traffic sources
# Post-processing procs
# 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_
head_ ->
handler_ -> handle()
insert
time_, uid_, next_, handler_
class Event {
class Handler {
public:
public:
Event* next_;
/* event list */
virtual void handle(Event* event) = 0;
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) {}
};
Modelo do escalonador
Modelo de filas simplificado:
t=1
t=1.01
Considere dois nodos
em uma rede Ethernet
A coloca um pacote na fila da LAN
LAN retira o pacote da fila e LAN e
dispara um evento de recepção em B
Modelo CSMA/CD detalhado:
A
B
t=1.0
A envia pacote para NIC;
NIC de A inicia “carrier sense”
t=1.005 NIC de A conclui cs, inicia tx
t=1.006 NIC de B começa a recepção do pacote
t=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]
$ns_ use-scheduler Heap
$ns_ at 300.5 “$self halt”
Simulador - métodos
Simulator instproc use-scheduler type {
$self instvar scheduler_
if [info exists scheduler_] {
if { [$scheduler_ info class] ==
"Scheduler/$type" } {
return
} else {
delete $scheduler_
}
}
set scheduler_ [new Scheduler/$type]
$scheduler_ now
}
Simulator instproc at args {
Simulator instproc run {} {
$self instvar scheduler_
...
return [eval $scheduler_ at $args]
return [$scheduler_ run]
}
}
Simulator instproc init args {
$self instvar useasim_
..._
set slinks_(0:0) 0
...
$self create_packetformat
$self use-scheduler Calendar
#$self use-scheduler List
...
}
Escalonador - Tipos

ListScheduler


Lista simples O(N)
HeapScheduler


Baseado em um Heap
O(logN)
CalendarScheduler



Baseado em Hash O(1)
SplayScheduler
RealTimerScheduler
Modos do escalonador
Modo interativo
Modo batch:
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->
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?


Usado principalmente em agentes, mas pode ser utilizado em
outros objetos




Um temporizador (timer) é um elemento que dispara um
determinado evento e que pode ser programado
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)


void resched(double delay)


Re-escalona o temporizador (similar ao sched, mas o
temporizador pode estar pendente)
void cancel()


Escalona um temporizador para disparar em “delay” segundos
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


virtual void handle (Event* e)


Consome um evento; faz um chamada para expire() e atribui o
valor adequado a status_
int status_


Este método deve ser preenchido com o código a ser
executado no instante de disparo do evento
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)


inline void _cancel()


{ (void)Scheduler::instance().schedule(this, &event_, delay); }
{ (void)Scheduler::instance().cancel(&event_); }
Esses códigos utilizam diretamente métodos do escalonador.
Definindo um Temporizador
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
}
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.
Exemplo – Retransmissão no
TCPclass RtxTimer : public TimerHandler {

public:
RtxTimer(TcpAgent
*a)no: TimerHandler()
Existem três temporizadores
declarados
agente TCP Tahoe {
definido em tcp.cc:
a_ = a;

rtx_timer_;
}
Temporizador de retransmissão
protected:

delsnd_timer_;
Atrasa ovirtual
envio do void
pacoteexpire(Event
por um pequeno tempo
*e);aleatório, de forma a
evitar efeitos cíclicos
TcpAgent *a_;

burstsnd_timer_;
};o TCP no envio de uma grande janela de tranmissão dividida
Auxilia




em várias partes menores
Em tcp.h existem três classes de temporizadores definidas:



class RtxTimer
class DelSndTimer
class BurstSndTimer
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::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::set_rtx_timer()
{ rtx_timer_.resched(rtt_timeout()); }
void TcpAgent::timeout( int tno )
{ ... }
void RtxTimer::expire( Event *e )
{
a_->timeout( TCP_TIMER_RTX );
}
/tcl/mcast/timer.tcl:
...
Timer instproc sched delay {
$self instvar ns_
$self instvar id_
$self cancel
set id_ [$ns_ after $delay "$self timeout"]
Diferença básica: ao contrário da implementação em C++,
} a sched() para um temporizador pendente
onde uma chamada
causa um abort()...
, sched e resched em OTcl possuem a mesma
funcionalidade
Temporizador em OTcl



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
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 recursivomú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
Pierresendo
L'Ecuyer.
números aleatórios, cada streams
composto
por
2,3x1015
S.K. Park
and R.W.
Miller.
Good parameters
and implementations
Random number
generation:
substreams.


for combined multiple recursive random
ones22are hard to find.
Cada substream possui um período Good
de 7,6x10
numberCommunications
generators.
of the ACM,
57
O período do gerador é de 3,1x10
Operations
Research,
1999
1988.
Geração de números
aleatórios



PierrenoL'Ecuyer,
Richard
Simard, E. Jack
Um gerador RNG default é criado
início da
simulação
Chen, and W. David Kelton.
(defaultRNG).
An object-oriented random number
Se múltiplas variáveis aleatórias são utilizadas durante uma
package with many long streams and
simulação, cada variável deve utilizar um objeto RNG distinto.
substreams.
Quando uma nova variável RNG
é criada,
à sua semente
Operations
Research,
2001. é
atribuído um valor de modo a gerar o próximo stream
independente de números aleatórios.
E também em:


A implementação permite umtools/rng.h
número máximo de 1,8x1019 var.
aleatórias.
tools/rng.cc
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.
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]
$sizeRNG next-substream
if {$argc > 1} {
}
puts "Usage: ns rng-test.tcl \[replication number\]"
# arrival_ is a exponential random variable describing the time
exit
# between consecutive packet arrivals
}
set arrival_ [new RandomVariable/Exponential]
set run 1
$arrival_ set avg_ 5
if { $argc == 1 } { set run [lindex $argv 0]
}
if { $run < 1 } { set run 1 }
# seed the default RNG
global defaultRNG
$defaultRNG seed 9999
$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
# create the RNGs and set them to the correct substream
# print the first 5 arrival times and sizes
set arrivalRNG [new RNG]
for {set j 0} {$j < 5} {incr j} {
set sizeRNG [new RNG]
puts [ format "%-8.3f %-4d" [ $arrival_ value ] \
for {set j 1} {$j < $run} {incr j} {
$arrivalRNG next-substream
[expr round([$size_ value])]]
}
Exemplo 1 - script
# Usage: ns rng-test.tcl [replication number]
$sizeRNG next-substream
if {$argc > 1} {
}
puts "Usage: ns rng-test.tcl \[replication number\]"
# arrival_ is a exponential random variable describing the time
exit
# between consecutive packet arrivals
}
set arrival_ [new RandomVariable/Exponential]
set run 1
$arrival_ set avg_ 5
if { $argc == 1 } { set run [lindex $argv 0]
}
if { $run < 1 } { set run 1 }
# seed the default RNG
global defaultRNG
$defaultRNG seed 9999
$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
# create the RNGs and set them to the correct substream
# print the first 5 arrival times and sizes
set arrivalRNG [new RNG]
for {set j 0} {$j < 5} {incr j} {
set sizeRNG [new RNG]
puts [ format "%-8.3f %-4d" [ $arrival_ value ] \
for {set j 1} {$j < $run} {incr j} {
$arrivalRNG next-substream
[expr round([$size_ value])]]
}
Exemplo - saída
% ns rng-test.tcl 1
% ns rng-test.tcl 5
6.358
5.828
1.469
0.732
4.002
0.691
0.204
8.849
2.111
3.200
4783
1732
2188
3076
626
1187
4924
857
4505
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]
# print the first 5 arrival times and sizes
if { $argc > 1 } {
for { set j 0 } { $j < 5 } { incr j } {
puts "Usage: ns rng-test2.tcl \[replication number\]"
puts [format "%-8.3f %-4d" [$arrivalRNG lognormal 5 0.1] \
[expr round([$sizeRNG normal 5000 100])]] }
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
}
Saída
% ns rng-test2.tcl 1
142.776 5038
174.365 5024
147.160 4984
169.693 4981
187.972 4982
Saída
% ns rng-test2.tcl 5
160.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;
/* 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)));
}
Saída
161.826 506
160.591 503
157.145 509
137.715 507
118.573 496
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 RandomVariable/Uniform]
set rng [new RNG]
$u set min_ 10
$rng seed 0
$u set max_ 20
set e [new RandomVariable/Exponential]
$u value
$e use-rng $rng

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.
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_;
};
Download

aula2-arquitetura