2015-03-22 3 views
0

Этот код для имитации сервера очереди MM1 (не очень важный факт). Я пытаюсь получить среднее значение количества пакетов в очереди для каждого прогона. Учитывая, что я прочитал значение лямбды из файла, изменить его, сохранить новое модифицированное значение его в файле еще раз, и запустить моделирование с текущим значением лямбды:ns: Avg: не может использовать нечисловую строку в качестве операнда «+»

#Create a simulator object 
set ns [new Simulator] 

global ns tracefile namf Qsize Qbw Qlost Qmon Avgvals InterArrivalTime lambda 

    proc readfile {filename} { 
    set f [open $filename] 
    set data [read $f] 
    close $f 
    return $data 
} 
proc writefile {filename data} { 
    set f [open $filename w] 
    puts -nonewline $f $data 
    close $f 
} 


#Define different colors for data flow (for NAM) 
$ns color 1 Blue 

#Open the NAM trace file 
set namf [open QMM1.nam w] 
$ns namtrace-all $namf 

set Qsize [open Qsize.tr w] 
set Qbw [open Qbw.tr w] 
set Qlost [open Qlost.tr w] 
set Avgvals [open Avgvals.tr a+] 
set tracefile [open out.tr w] 
$ns trace-all $tracefile 


#set lambda and Mu 

set mu  1100.0 

catch {set lambda [readfile LamdaValue.tr]} 
set lambda [expr {$lambda + 100.0}] 
writefile LamdaValue.tr $lambda 


#Create the Node to generate the traffic Queue and Server 
set n1 [$ns node] 
set n2 [$ns node] 

# Since packet sizes will be rounded to an integer 
# number of bytes, we should have large packets and 
# to have small rounding errors, and so we take large bandwidth 

#Create link between the two nodes 
set link [$ns simplex-link $n1 $n2 100kb 0ms DropTail] 

#Monitor the queue for link (n1-n2) for nam 
$ns simplex-link-op $n1 $n2 queuePos 0.5 


#set up a large Queue capacity (n1-n2) 
$ns queue-limit $n1 $n2 100000 

# generate random interarrival times and packet sizes 

#Set arrivals to be exponential 
set InterArrivalTime [new RandomVariable/Exponential] 

#Avg=1/lambda 
#$InterArrivalTime set avg_ [expr 1/$lambda] 


set pktSize [new RandomVariable/Exponential] 
$pktSize set avg_ [expr 100000.0/(8*$mu)] 

#Set src to use UDP 
set src [new Agent/UDP] 
$src set fid_ 1 
$ns attach-agent $n1 $src 

# queue monitoring, write statistics to queueStat 
set Qmon [$ns monitor-queue $n1 $n2 [open queueStat.out w] 0.1] 
$link queue-sample-timeout 


proc record {} { 
global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda 
set time 0.05 
set now [$ns now] 

# print in the file $Qsize the current queue size 
# print in the file $Qbw the current used bandwidth 
# print in the file $Qlost the loss rate 

$Qmon instvar parrivals_ pdepartures_ bdrops_ bdepartures_ pdrops_ 
puts $Qsize "[expr $parrivals_-$pdepartures_-$pdrops_]" 
puts $Qbw "$now [expr $bdepartures_*8/1024/$time]" 
set bdepartures_ 0         
puts $Qlost "$now [expr $pdrops_/$time]" 
$ns at [expr $now+$time] "record" 
} 


proc finish {} { 
    global ns tracefile namf Qsize Qbw Qlost Qmon 
    $ns flush-trace 
    #Close the NAM trace file 
    close $namf 
    close $Qsize 
    close $Qbw 
    close $Qlost 
    close $tracefile 
    #Execute NAM on the trace file 
    #exec ./nam QMM1.nam & 
    exit 0 
} 

proc sendpacket {} { 
    global ns src InterArrivalTime pktSize 
    set time [$ns now] 
    $ns at [expr $time + [$InterArrivalTime value]] "sendpacket" 
    set bytes [expr round ([$pktSize value])] 
    $src send $bytes 
} 



proc Avg {} { 
global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda 

set sum 0.0 
set c 1 

set fid [open Qsize.tr r] 
    set txt [read $fid] 
    close $fid 

    foreach {x} $txt { 
    set sum [expr {$sum + $x}] 
    incr c 1 
    } 


set avg [expr $sum/$c] 
puts $Avgvals "$lambda $avg" 

} 

set sink [new Agent/Null] 
$ns attach-agent $n2 $sink 
$ns connect $src $sink 

proc repeatSim {} { 
     global lambda 
     if {$lambda < 1002} { 
     exec ./ns QMM1.tcl & 
     } 
} 


    #Avg=1/lambda 
    $InterArrivalTime set avg_ [expr 1/$lambda] 
    puts "Lambda = $lambda" 
     puts "Mu = $mu" 
    $ns at 0.0 "record" 
    $ns at 0.0001 "sendpacket" 
    $ns at 1000.0 "Avg" 
    $ns at 1000.0 "repeatSim" 

#Run the simulation 
$ns run 

Проблемы в том, что он делает первые три самостоятельных звонка от:

proc repeatSim {} { 
     global lambda 
     if {$lambda < 1002} { 
     exec ./ns QMM1.tcl & 
     } 
} 

Тогда это дает ошибку в названии. Полный текст заявления об ошибке:

ns: Avg: can't use non-numeric string as operand of "+" 
    while executing 
"expr {$sum + $x}" 
    (procedure "Avg" line 12) 
    invoked from within 
"Avg" 

Я попробовал несколько манипуляций в коде, но ошибка все еще показывает, таким же образом. Можете ли вы сказать, в чем проблема?

+1

Я не эксперт в 'ns2'.Но, глядя на сообщение об ошибке, которое вы получили, кажется, что значение 'x', считанное из файла, может быть алфавитом или специальным символом вместо численного значения. Вы инициализировали 'sum' как 0.0. Итак, странный человек, который явно указывает на проблему с 'x'. Вы можете это проверить? – Dinesh

+0

Вам действительно нужно опубликовать весь этот код, чтобы показать нам проблему? Измените свой вопрос и удалите все, что непосредственно не затрагивает проблему. –

ответ

2

Пошаговое руководство о том, как более тщательно отлаживать код

Давайте посмотрим на сообщении об ошибке.

 
ns: Avg: can't use non-numeric string as operand of "+" 
    while executing 
"expr {$sum + $x}" 
    (procedure "Avg" line 12) 
    invoked from within 
"Avg" 

Он говорит, что один из аргументов оператора + не является числом, и это было в призвании expr {$sum + $x} на 12-й линии процедуры, называемой Avg.

Какой аргумент может быть? Что может быть действительно не так? Давайте посмотрим на ваш код (для пояснения).

proc Avg {} { 
    global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda 

    set sum 0.0 
    set c 1 

    set fid [open Qsize.tr r] 
    set txt [read $fid] 
    close $fid 

    foreach {x} $txt { 
     set sum [expr {$sum + $x}] 
     incr c 1 
    } 

    set avg [expr $sum/$c] 
    puts $Avgvals "$lambda $avg" 
} 

ОК, линия, которая имея проблемы заключается в foreach и он используется, чтобы добавить слова из $txt (то есть, чтение из файла) в виде чисел с плавающей точкой (с sum инициализируется 0.0). Ну, так как sum продолжит удерживать число с плавающей запятой, если все значения для добавления являются числовыми, у нас должно есть проблема, что одно из слов в файле не является числом. Это не может быть ничего, потому что само выражение находится в фигурных скобках, что гарантирует надежную интерпретацию на уровне Tcl. (expr $sum/$c не так хорош, хотя будет вести себя предсказуемо в Tcl 8.5 и 8.6, где мы используем пользовательский высоконадежный конвертер с плавающей запятой и строкой вместо немного шаткого, который входит в стандартную библиотеку C.)

Мы можем 't сообщить из предоставленной информации, что такое нарушающая ценность; трассировка ошибки не регистрировала его (он не содержит все, или это было бы слишком громоздким), и вы не предоставили провал. Если вы собираетесь отлаживать, вы можете попробовать изменить код для этого:

proc Avg {} { 
    global ns Qmon Qsize Qbw Qlost n1 n2 Avgvals lambda 

    set sum 0.0 
    set c 1 

    set fid [open Qsize.tr r] 
    set txt [read $fid] 
    close $fid 

    foreach {x} $txt { 
     if {[catch { 
      set sum [expr {$sum + $x}] 
      incr c 1 
     }] { 
      puts "The value at index #$c ('$x') is not numeric" 
     } 
    } 

    set avg [expr $sum/$c] 
    puts $Avgvals "$lambda $avg" 
} 

Если выясняется, что проблема заключается в том, что есть дополнительное metasyntax в файле, который вы читаете из, вам необходимости чтобы справиться с этим, прежде чем суммировать значения.

Ваш код также имеет ошибку: «средний» будет немного низким, потому что c заканчивается слишком большим.