#!/usr/bin/python
#
# Copyright (C) 2007 by Johan De Taeye
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This library 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 Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.8.0/test/scalability_2/runtest.py $
# revision : $LastChangedRevision: 1012 $ $LastChangedBy: jdetaeye $
# date : $LastChangedDate: 2009-08-06 08:14:40 +0200 (Thu, 06 Aug 2009) $
# This script is a simple, generic model generator. A number of different
# models are created with varying number of clusters, depth of the supply path
# and number of demands per cluster. By evaluating the runtime of these models
# we can evaluate different aspects of Frepple's scalability.
#
# This test script is meant more as a sample for your own tests on evaluating
# scalability.
#
# The autogenerated supply network looks schematically as follows:
# [ Operation -> buffer ] ... [ -> Operation -> buffer ] [ Delivery ]
# [ Operation -> buffer ] ... [ -> Operation -> buffer ] [ Delivery ]
# [ Operation -> buffer ] ... [ -> Operation -> buffer ] [ Delivery ]
# [ Operation -> buffer ] ... [ -> Operation -> buffer ] [ Delivery ]
# [ Operation -> buffer ] ... [ -> Operation -> buffer ] [ Delivery ]
# ... ...
# Each row represents a cluster.
# The operation+buffer are repeated as many times as the depth of the supply
# path parameter.
# In each cluster a single item is defined, and a parametrizable number of
# demands is placed on the cluster.
import os, os.path, sys, random
# This function generates a random date
def getDate():
month = "%02d" % (int(random.uniform(0,12))+1)
day = "%02d" % (int(random.uniform(0,28))+1)
return "2007-%s-%sT00:00:00" % (month,day)
# This routine creates the model data file.
# The return value is an indication of the size of the model.
def create (cluster, demand, level):
# Initialize
size = 0
out = open("input.xml","wt")
print >>out, "<plan xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
# Items
print >>out, "<items>"
for i in range(cluster):
++size
print >>out, ("<item name=\"Item C%d\">" +
"<operation name=\"Del C%d\"> <flows>" +
"<flow xsi:type=\"flow_start\" quantity=\"-1\">" +
"<buffer name=\"Buffer C%dL1\"/></flow>" +
"</flows></operation></item>") % (i,i,i)
print >>out, "</items>"
# Demands
print >>out, "<demands>"
for i in range(cluster):
for j in range(demand):
size += 2 # since a demand will result in multiple operationplans
print >>out, ("<demand name=\"Demand C%dD%d\" " +
"quantity=\"1\" due=\"%s\">" +
"<item name=\"Item C%d\"/></demand>") % (i,j,getDate(),i)
print >>out, "</demands>"
# Operations
print >>out, "<operations>"
for i in range(cluster):
for j in range(level):
size += 2
print >>out, ("<operation name=\"Oper C%dO%d\" " +
"xsi:type=\"operation_fixed_time\" " +
"duration=\"PT%dH\"> <flows>" +
"<flow xsi:type=\"flow_end\" quantity=\"1\">" +
"<buffer name=\"Buffer C%dL%d\">" +
"<producing name=\"Oper C%dO%d\"/></buffer></flow>" +
"<flow xsi:type=\"flow_start\" quantity=\"-1\">" +
"<buffer name=\"Buffer C%dL%d\"/></flow>" +
"</flows></operation>") % (i, j, 24*int(random.uniform(0,10)+1), i, j, i, j, i, j+1)
# Create material supply
for i in range(cluster):
print >>out, ("<operation name=\"Supply C%d\"> " +
"<flows><flow xsi:type=\"flow_end\" quantity=\"1\">" +
"<buffer name=\"Buffer C%dL%d\"/>" +
"</flow></flows></operation>") % (i, i, level+1)
print >>out, "</operations>\n<operationplans>"
for i in range(cluster):
print >>out, ("<operationplan id=\"%d\" operation=\"Supply C%d\" " +
"start=\"2007-05-01T00:00:00\" quantity=\"%d\" " +
"locked=\"true\" />") % (i+1, i, demand)
print >>out, "</operationplans>"
# Tail of the output file
print >>out, "</plan>"
out.close()
# Return size indication
return size
# Initialize random number generator in a reproducible way
random.seed(100)
# Loop over all cluster values
runtimes = {}
print "Clusters\tDemands\tLevels\tRuntime"
for cluster in [100,200,300]:
# Loop over all demand values
for demand in [10,20,30]:
# Loop over all level values
for level in [1,5,9]:
# Creating model data file
size = create(cluster, demand, level)
# Run the model
starttime = os.times()
out = os.popen(os.environ['EXECUTABLE'] + " ./commands.xml")
while True:
i = out.readline()
if not i: break
print i.strip()
if out.close() != None:
print "Planner exited abnormally"
sys.exit(1)
# Measure the time
endtime = os.times()
runtimes[size] = endtime[4]-starttime[4]
print "%d\t%d\t%d\t%.3f" % (cluster,demand,level,runtimes[size])
# Clean up the files
os.remove("input.xml")
os.remove("output.xml")
#if os.path.isfile("input_%d_%d_%d.xml" % (cluster,demand,level)):
# os.remove("input_%d_%d_%d.xml" % (cluster,demand,level))
#if os.path.isfile("output_%d_%d_%d.xml" % (cluster,demand,level)):
# os.remove("output_%d_%d_%d.xml" % (cluster,demand,level))
#os.rename("input.xml", "input_%d_%d_%d.xml" % (cluster,demand,level))
#os.rename("output.xml", "output_%d_%d_%d.xml" % (cluster,demand,level))
# A pass criterium could be defined here.
# Right now the test pass when all cases finish successfully, and the timing
# isn't considered to evaluate pass or fail.
# Since the data import and bottleneck are the most timeconsuming operations
# a timing that scales close to linear with the model size is expected.
print "\nTest passed"
|