#!/usr/bin/env python
#
# A Python PDQ model of the SimPy simulator example 
# http://simpy.sourceforge.net/examples/Jackson%20network.htm
#
# Created by NJG on Thu Oct 28 10:16:59 PDT 2004
# Updated by NJG on 8:40:28 PM Thu, Apr 19, 2007

import pdq
import sys 
from numpy import *
from numpy.linalg import solve

class CommsNetwork:
   """ Constructor for the queueing network to be solved """
   def __init__(selfnetnamedebugFlag):
      """ Globals should be contained :-)  """
      self.name = netname
      self.debugging = debugFlag
      self.arrivRate = 0.50
      self.work = "Traffic"
      self.router = ["Router1""Router2""Router3"]
      self.servTime = [1.02.01.0]

# Create a network instance
comms = CommsNetwork("SimPy Network"1""" Construct and solve traffic equations numerically using NumPy 
From the queueing network diagram, we have:
L1 = 0.5 + 0.2 L3
L2 = 0.5 L1
L3 = 0.5 L1 + 0.8 L2

Rearrange the terms into matrix form:
  1.0 L1 + 0.0 L2 - 0.2 L3 = 0.5
- 0.5 L1 + 1.0 L2 + 0.0 L3 = 0.0
- 0.5 L1 - 0.8 L2 + 1.0 L3 = 0.0
  
All diagonal coeffs should be 1.0
"""
# Copy above matrix coeffs into an NumPy array
a = array([[ 1.0,  0.0, -0.2], 
           [-0.5,  1.0,  0.0],
           [-0.5, -0.8,  1.0]])

# RHS of the traffic eqns
b = array([0.50.00.0])

# Solve the traffic eqns for L1, L2, and L3
L = solve(a,b)

# Use L matrix to calculate visit ratios at each router
v = array([L[0]/comms.arrivRateL[1]/comms.arrivRateL[2]/comms.arrivRate])

# Service demands
D = array([v[0]*comms.servTime[0], v[1]*comms.servTime[1], v[2]*comms.servTime[2]])

""" Use the service demands derived from the solved traffic equations 
    to parameterize and solve PyDQ queueing model 
"""
pdq.Init("SimPy Network in PyDQ")

# Create the traffic arriving into the network
s = pdq.CreateOpen(comms.workcomms.arrivRate)
pdq.SetWUnit("Msgs")
pdq.SetTUnit("Time")

# Create network routers 
for i in range(len(comms.router)):
   n = pdq.CreateNode(comms.router[i], pdq.CENpdq.FCFS)
   pdq.SetDemand(comms.router[i], comms.workD[i])

# Solve and report the peformance measures
pdq.Solve(pdq.CANON)
pdq.Report();