Example #1
0
func main() {
	var finalTick, simTicks int

	// Run the simulation for 24 hours (a tick represents a millisecond)
	simTicks = 86400 * 1000

	fmt.Printf("arrival_interval,utilization,avg_queue\n")
	for ai := 900; ai < 3000; ai += 50 {
		sys := &BlogSystem{ArrivalInterval: float64(ai)}
		finalTick = qsim.RunSimulation(sys, simTicks)
		fmt.Printf("%d,%0.3f,%0.3f\n",
			ai, 1.0-float64(sys.IdleTime)/float64(finalTick), float64(sys.QueueSum)/float64(sys.QueueCount))
	}
}
Example #2
0
// Simulates a blood bank.
//
// – Any blood unit older than 35 days is thrown in the trash.
// – There is only one queue, representing the bank itself.
// - There are two processors. One represents the trash, and the other
//   represents actual use in transfusion.
// – Each tick is a minute.
//
// Arguments, in order:
//
// - Daily Maximum Draw Rate (in units/day, as an int)
// - Maximum Bank Occupancy (in units, as an int)
// - Daily Mean Transfusion Rate (in units/day, as a float)
// - (optional) The word "test", indicating that only 1 sim should be run.
//
// We output a CSV row with the following values, in order:
//
// - Total number of ticks ("minutes") for which simulations collected data
// - Number of simulations
// - Number of units used in transfusions
// - Number of units thrown out
// - Number of transfusions aborted due to lack of blood
// - 90th percentile age of units used in transfusions
// - A value for each member of `thresholds` (see below) indicating the number of units
//   used in transfusions over that age in days
func SimBloodBank() {
	var simTicks, nSims, simsPerCpu, statsStart int
	var maxDrawRate, maxOccupancy int
	var maxDrawRate64, maxOccupancy64 int64
	var meanTransfusionRate float64
	type simResult struct {
		Done                           bool
		NumTossed, NumUsed, NumAborted int
		UnitAges                       []int
		AgeCounts                      []int
	}
	var nTossed, nUsed, nAborted int
	var unitAges, ageCounts, thresholds []int
	var ch chan simResult
	var cpu, nCpu, routinesDone int
	var err error

	if len(os.Args) > 4 && os.Args[4] == "test" {
		nCpu = 1
		nSims = 1
		simTicks = 2 * 365 * 1440
	} else {
		nCpu = 16
		nSims = 64
		simTicks = 40 * 365 * 1440
	}
	simsPerCpu = nSims / nCpu
	// Don't start collecting stats until a year goes by
	statsStart = 365 * 1440

	thresholds = []int{5 * 1440, 10 * 1440, 15 * 1440, 20 * 1440, 25 * 1440, 30 * 1440}
	unitAges = make([]int, 0)
	ageCounts = make([]int, len(thresholds))

	maxDrawRate64, err = strconv.ParseInt(os.Args[1], 10, 0)
	if err != nil {
		panic("Failed to parse mean draw rate")
	}
	maxDrawRate = int(maxDrawRate64)
	maxOccupancy64, err = strconv.ParseInt(os.Args[2], 10, 0)
	if err != nil {
		panic("Failed to parse maximum occupancy")
	}
	maxOccupancy = int(maxOccupancy64)
	meanTransfusionRate, err = strconv.ParseFloat(os.Args[3], 0)
	if err != nil {
		panic("Failed to parse mean transfusion rate")
	}

	ch = make(chan simResult)
	for cpu = 0; cpu < nCpu; cpu++ {
		go func(cpu int) {
			var i int
			for i = cpu*simsPerCpu + 1; i <= (cpu+1)*simsPerCpu; i++ {
				var rslt simResult
				rslt = simResult{
					AgeCounts: make([]int, len(thresholds)),
				}
				var j int
				for j = 0; j < simsPerCpu; j++ {
					sys := &BloodBankSystem{
						Thresholds:          thresholds,
						StatsStart:          statsStart,
						MaxDrawRate:         maxDrawRate,
						MaxOccupancy:        maxOccupancy,
						MeanTransfusionRate: meanTransfusionRate,
					}
					qsim.RunSimulation(sys, simTicks)

					rslt.NumTossed += sys.NumTossed
					rslt.NumUsed += sys.NumUsed
					rslt.NumAborted += sys.NumAborted
					rslt.UnitAges = append(rslt.UnitAges, sys.UnitAges...)
					var k int
					for k, _ = range rslt.AgeCounts {
						rslt.AgeCounts[k] = sys.AgeCounts[k]
					}
				}
				ch <- rslt
			}
			ch <- simResult{Done: true}
		}(cpu)
	}

	for routinesDone < nCpu {
		var rslt simResult
		rslt = <-ch
		if rslt.Done {
			routinesDone++
			continue
		}
		nTossed += rslt.NumTossed
		nUsed += rslt.NumUsed
		nAborted += rslt.NumAborted
		unitAges = append(unitAges, rslt.UnitAges...)
		for i, _ := range thresholds {
			ageCounts[i] += rslt.AgeCounts[i]
		}
	}

	sort.Ints(unitAges)
	ind := int(9 * len(unitAges) / 10)
	p90UnitAge := unitAges[ind]

	fmt.Printf("%d,%d,%d,%d,%d,%d",
		(simTicks-statsStart)*nSims,
		nSims,
		nUsed,
		nTossed,
		nAborted,
		p90UnitAge,
	)
	for i, _ := range thresholds {
		fmt.Printf(",%d", ageCounts[i])
	}
	fmt.Printf("\n")
}
Example #3
0
// Simulates a line of porta-potties at a big concert.
//
// – People arrive very frequently, but if the queues are too long they leave.
// – There are 15 porta-potties, each with its own queue. Once a person enters
//   a queue, they stay in it until that porta-potty is vacant.
// – The time taken to use a porta-potty is normally distributed with a
//   different mean for men and women.
// – Most people just pick a random queue to join (as long as it's no longer
//   than the shortest queue), but some people use the strategy of getting
//   into the queue with the highestman:woman ratio (again, as long as it's no
//   longer than the shortest queue), on the theory that this will get them to
//   the front of the queue faster.
// – Each tick is a millisecond (we use very small ticks to minimize the
//   rounding error inherent in picking integer times from a continuous
//   distribution.
func SimPortaPotty() {
	var simTicks, simsPerProb int
	var probStep float64
	type simResult struct {
		Done                                        bool
		PStrategy                                   float64
		SumStrategizerWaits, SumNonStrategizerWaits int
		NumStrategizers, NumNonStrategizers         int
	}
	var ch chan simResult
	var cpu, nCpu, nProbs, probsPerCpu, routinesDone int

	fmt.Println("pStrategy,avgStratWait,avgNonStratWait,avgWait")

	nCpu = 5
	nProbs = 100
	probStep = .01
	probsPerCpu = nProbs / nCpu
	// Run each simulation for 14 days
	simTicks = 14 * 86400 * 1000
	simsPerProb = 40

	ch = make(chan simResult)
	for cpu = 0; cpu < nCpu; cpu++ {
		go func(cpu int) {
			var i int
			for i = cpu*probsPerCpu + 1; i <= (cpu+1)*probsPerCpu; i++ {
				var pStrategy float64
				var rslt simResult
				pStrategy = probStep * float64(i)
				rslt = simResult{
					Done:      false,
					PStrategy: pStrategy,
				}
				var j int
				for j = 0; j < simsPerProb; j++ {
					sys := &PortaPottySystem{
						PStrategy:  pStrategy,
						StatsStart: 200000000,
					}
					qsim.RunSimulation(sys, simTicks)

					rslt.SumStrategizerWaits += sys.SumStrategizerWaits
					rslt.SumNonStrategizerWaits += sys.SumNonStrategizerWaits
					rslt.NumStrategizers += sys.NumStrategizers
					rslt.NumNonStrategizers += sys.NumNonStrategizers
				}
				ch <- rslt
			}
			ch <- simResult{Done: true}
		}(cpu)
	}

	for routinesDone < nCpu {
		var rslt simResult
		rslt = <-ch
		if rslt.Done {
			routinesDone++
			continue
		}
		avgStrategizerWait := float64(rslt.SumStrategizerWaits) / float64(rslt.NumStrategizers)
		avgNonStrategizerWait := float64(rslt.SumNonStrategizerWaits) / float64(rslt.NumNonStrategizers)
		avgWait := float64(rslt.SumStrategizerWaits+rslt.SumNonStrategizerWaits) / float64(rslt.NumStrategizers+rslt.NumNonStrategizers)
		fmt.Printf("%0.2f,%0.2f,%0.2f,%02.f\n", rslt.PStrategy, avgStrategizerWait/1000.0, avgNonStrategizerWait/1000.0, avgWait/1000.0)
	}
}