Multi-region Capacity Planning Model with Contracts of Varying Duration under Uncertainty: A movou Satellite Capacity Acquisition Case Study MASSACHUSETTS INSflJTME OF TECHOLOGY by JUN 19 2014 John M. Lydiard IV LIBRARIES Submitted to the Engineering Systems Division in partial fulfillment of the requirements for the degree of Master of Science in Engineering Systems at the MASSACHUSETTS INSTITUTE OF TECHNOLOGY June 2014 This material is a declared work of the U.S. Government and is not subject to copyright protection in the United States. Signature redacted A uthor .................................... Engineing Systems Division May 18, 2014 / 1 Certified by................. Signature redacted Olivier L. de Weck Professor of Engineering Systems Thesis Supervisor Accepted by......Signature redacted Richard Larson Mitsui Professor of Engineering Systems Chair, Engineering Systems Division Education Committee Multi-region Capacity Planning Model with Contracts of Varying Duration under Uncertainty: A Satellite Capacity Acquisition Case Study by John M. Lydiard IV Submitted to the Engineering Systems Division on May 18, 2014, in partial fulfillment of the requirements for the degree of Master of Science in Engineering Systems Abstract This paper highlights the issues associated with and presents a modeling framework for long-term capacity planning problems constrained in a similar fashion to satellite capacity acquisition. Although ambiguities exist, the satellite capacity planning problem also contains many clearly defined constraints. In the immediate time horizon, universal satellite capacity is fixed, as satellite launches are rare, and each incremental satellite launch only marginally increases capacity. In the world of Commercial Satellite Communications (COMSATCOM), satellites have fixed coverage areas as they are typically in geo-synchronous orbit. Other military applications such as observation and satellite phone require, low-earth orbit and medium-earth orbit satellites. The contracts used to acquire satellite capacity from the commercial sector also clearly define constraints, such as start and end date, bandwidth, price per unit bandwidth and allocated satellite system, which also implies frequency and available capacity. The paper first reviews the issues involved with planning capacity acquisition, and then presents a modeling framework for developing strategies to meet criteria and minimize cost. A simulation environment is developed for testing contracts and satellites of different parameters against varying demand distributions. A dynamic program is used to solve the integer program associated with selecting satellite capacity levels to cover demand. Thesis Supervisor: Olivier L. de Weck Title: Professor of Engineering Systems 3 4 Acknowledgments I thank my advisor, Oli, for providing guidance throughout my time at MIT and for encouraging me to explore my own interests within Engineering Systems. I also thank Professor George Kocur for being a tremendous teacher and mentor in and out of the classroom. MIT Lincoln Laboratory and the US Air Force provided me the opportunity to study at MIT. I sincerely appreciate the opportunity. In addition, I acknowledge my group leader, Dr. Marc Viera, for his support and advice, and Mr. John Kuconis for his integral role in the Military Fellows Program. Lastly, I thank my parents for being fantastic role models and for motivating me in every chapter of my life. This work was sponsored by the Department of the Air Force under contract FA872105-C-0002. Opinions, interpretations, conclusions, and recommendations are those of the author and are not necessarily endorsed by the United States Government. 5 6 Contents 1 Introduction 15 1.1 Motivation and Background . . . . . . . . . . . . . . . . . . . . . . . 15 1.2 Conclusions from DBB Analysis . . . . . . . . . . . . . . . . . . . . . 18 1.3 RAND - Wideband Investment Options . . . . . . . . . . . . . . . . . 18 1.4 RAND - Providers and Contracts . . . . . . . . . . . . . . . . . . . . 23 1.5 Conclusions from RAND Study . . . . . . . . . . . . . . . . . . . . . 24 1.6 Emerging Technological Uses and Growth . . . . . . . . . . . . . . . 25 1.6.1 Demand Growth Within Contingencies . . . . . . . . . . . . . 26 1.6.2 Global Demand Growth . . . . . . . . . . . . . . . . . . . . . 27 Where the RAND model left off . . . . . . . . . . . . . . . . . . . . . 30 1.7 2 Mathematical Formulation and DP Model 2.1 2.2 33 Integer Program Formulation . . . . . . . . . . . . . . . . . . . 33 2.1.1 Parameters of Interest . . . . . . . . . . . . . . . . . . . 33 2.1.2 Decision Variables . . . . . . . . . . . . . . . . . . . . . 34 2.1.3 Objective Function . . . . . . . . . . . . . . . . . . . . . 34 2.1.4 Constraints . . . . . . . . . . . . . . . . . . . . . . . . . 35 Dynamic Programming Solver . . . . . . . . . . . . . . . . . . . 35 2.2.1 Modeling Methodology . . . . . . . . . . . . . . . . . . . 35 2.2.2 Stages, States, Nodes and Arcs . . . . . . . . . . . . . . 36 2.2.3 Modeling Questions . . . . . . . . . . . . . . . . . . . . . 37 2.2.4 Model Assumptions . . . . . . . . . . . . . . . . . . . . . 37 2.2.5 Tradeoffs Between Long and Short Term Contracts . . . 39 7 . . . . . . . . . . . . . . . 39 . . . . . . . . . . . . . . . 44 Pseudo-code . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Standalone Options . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.2.6 2.3 DP Simulation - Adding Uncertainties 2.3.1 2.4 3 49 Results . . . . . . . . . . . . . . 49 Deterministic Results . . . . . . . . . . . . . . . 49 3.2 Results with Options Contracts . . . . . . . . . . . . . 53 3.3 Results with Multiple Runs . . . . . . . . . . . . . . . 53 3.4 Time Complexity . . . . . . . . . . . . . . . . . . . . . 57 3.4.1 Leading Indicator . . . . . . . . . . . . . . . . . 57 3.4.2 Adding Detail without Adding Time . . . . . . 58 3.4.3 An Alternative Representation . . . . . . . . . . 60 3.1 Small Deterministic Example 3.1.1 4 Pseudo-code . . . . . . . . . . . 61 Conclusions 4.1 Thesis Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.2 Future Work and Potential Uses . . . . . . . . . . . . . . . . . . . . . 62 65 A DP Code - Java Contract Scheduler . . . . . . . . . . . . . 65 A.2 Demand Generator . . . . . . . . . . . . . 75 A.3 Satellite . . . . . . . . . . . . . . . . . . . 81 A.4 Main() Method . . . . . . . . . . . . . . . 84 A.1 B Web Application Code - Ruby on Rails 93 B .1 V iew . . . . . . . . . . . . . . . . . . . . . 93 Controller . . . . . . . . . . . . . . . . . . 117 B .3 M odels . . . . . . . . . . . . . . . . . . . . 118 B.4 Database Migrations . . . . . . . . . . . . 120 B.2 8 List of Figures 1-1 Defense Business Board - COMSAT Acquisition Approaches . . . . . 17 1-2 RAND Growth Projections . . . . . . . . . . . . . . . . . . . . . . . . 19 1-3 RAND Contingency Data . . . . . . . . . . . . . . . . . . . . . . . . 22 1-4 RAND - Effect of Delivery Lag on Sat Purchase . . . . . . . . . . . . 24 1-5 Mbps Used Per 5000 Troops . . . . . . . . . . . . . . . . . . . . . . . 27 1-6 Futron COMSAT Demand Projection . . . . . . . . . . . . . . . . . . 28 1-7 Rising Government Contract Costs . . . . . . . . . . . . . . . . . . . 28 1-8 Transponder Equivalent and Mbps . . . . . . . . . . . . . . . . . . . 29 1-9 Futron - Supply Chart by Provider, Region and Frequency . . . . . . 31 3-1 Two Satellite, Three Region, Twelve Mo. Contract Results . . . . . . 50 3-2 Two Satellite, Three Region, Six Mo. Contract Results . . . . . . . . 50 3-3 Two Satellite, Three Region, Three Mo. Contract Results . . . . . . . 51 3-4 BW Provided by Contract and Demanded in Region 1 . . . . . . . . 51 3-5 Cumulative Cost by Contract of a run . . . . . . . . . . . . . . . . . 51 3-6 Cumulative Costs with Fixed Capacity Contract Types . . . . . . . . 52 3-7 BW Supplied and Demand for Region 1 With Multiple Contract Types 53 3-8 Single Run With Options Contract 3-9 Cost Histogram by Contract for Two Sat, Three Reg . . . . . . . . . . . . . . . . . . . 54 . . . . . . . . . 55 . . . . . . . . . . . . . . . . . . . . 55 3-11 Cost Histogram - Nine Contract Types . . . . . . . . . . . . . . . . . 56 3-12 Cumulative Cost - Nine Contract Types . . . . . . . . . . . . . . . . 56 3-13 Number of Steps to Nodes . . . . . . . . . . . . . . . . . . . . . . . . 58 3-10 Satellite Level by Contract Type 9 10 List of Tables 1.1 RAND - Lease Prices and Contract Duration . . . . . . . . . . . . . . 23 1.2 Example Regional Cost Comparison . . . . . . . . . . . . . . . . . . . 30 3.1 Average Utilization for All Regions . . . . . . . . . . . . . . . . . . . 52 3.2 Utilization as Precursor to Spending . . . . . . . . . . . . . . . . . . 58 11 12 List of Algorithms 1 Dynamic Program - Contract Scheduler Constructor . . . . . . . . . . 40 2 Dynamic Program - Build Source . . . . . . . . . . . . . . . . . . . . 41 3 Dynamic Program - Build Center . . . . . . . . . . . . . . . . . . . . 42 4 Dynamic Program - Build Sink . . . . . . . . . . . . . . . . . . . . . 43 5 Dynamic Program - Back Path . . . . . . . . . . . . . . . . . . . . . 43 6 Distribution Generator . . . . . . . . . . . . . . . . . . . . . . . . . . 44 7 Demand Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 13 14 Chapter 1 Introduction 1.1 Motivation and Background The Office of the Deputy Secretary of Defense commissioned a report analyzing the opportunities in the commercial satellite industry space to address Department of Defense (DoD) demand for Commercial Satellite Communications (COMSAT). The tasked force, the Defense Business Board (DBB), found commercially acquired services to account for approximately 40% of DoD satellite communications (SATCOM) services at $640M annually. The private sector provides many contract vehicles for acquisition ranging from immediate (i.e. daily or weekly contracts) to annual or multi-year agreements, with either upfront or periodic costs. However, several policies limit decision making including Federal Acquisition Regulations (FAR), Planning, Programming, Budgeting and Execution, and statutory limits [5, p. 1]. The SATCOM market can be divided into three sub-categories: Military SATCOM (MILSAT), Civillian Government SATCOM (GOVSAT), and Commerical SATCOM (COMSAT). The DoD controls all MILSAT procurement through the United States Air Force Space and Missile Command (SMC). The Defense Information Systems Agency (DISA) uses General Services Administration (GSA) contracts to purchase COMSAT solutions. SATCOM comprises 58% of the total satellite market worldwide. Within the SATCOM market, COMSAT constitutes 65% of capacity, where as MILSAT and GOVSAT only represent 15% and 20% respectively 15 [5, p. 2]. Military procured satellites have many different requirements, including nuclear hardening and additional security measures, as well as different attributes, such as much longer procurement time horizons and higher associated costs than commercial satellites. This thesis focuses on the case study of COMSAT acquisition, but the analysis and model could be extended to incorporate long-term projects and will be discussed later. Procurement for COMSAT is split between two categories of contract vehicles: one year leases and "spot market" purchases which comprise 75% and 25% of services acquired respectively. According to the report, DISA expenditures are expected to grow to $3-$5B over the next fifteen years [5, p. 4]. According to Northern Sky Research, DoD's SATCOM needs will increase by 68% over the next ten years due to a policy shift to focus on Asia-Pacifc affairs, increased Naval activity, increased surveillance of world events and a larger role in the "war on drugs" [5, p. 5]. Technological advancements have given rise to the COMSAT industry as demand for consumer services such as satellite television, including high definition, satellite internet, and radio have increased. COMSAT "fill-rates" are as high as 80%, without DoD participation, DoD must prepare for instances of limited supply, and therefore rising prices [5, p.4]. COMSAT is less expensive and has shorter development cycles than MILSAT. The average time from concept to launch is 3-4 years in the private sector, and 5-15 years for DoD projects [5, p. 6]. Considering the tightening military budget con- straints, and that sequester-level funding returns in 2016, DoD must use every dollar as efficiently as possible. Given the constricting budget and forecasted rising demand, COMSAT will play a critical role in supplying the military necessary bandwidth to accomplish its mission. "Currently, DISA uses indefinite deliver, indefinite quantity (IDIQ) contracts to obtain three types of commercial satellite services: (1) "bent pipe" service; (2) buy bandwidth directly; and (3) provide end-to-end support services" [5, p. 8]. The GSA defines the circumstance of IDIQ use as, "when GSA can't determine, above a specified minimum, the precise quantities of supplies or services that the government will require during the contract period" [1]. The exact mechanisms of the contract 16 Traditional and non-traditional approaches for COMSAT acquisition Traditional and non-traditional obstacles for COMSAT acquisition Buy to Lease Make offer to a commercial operator for system use and obtain quid pro quo global service access for discount/zero ch~argetrauyv.loasevcacesdl tFunds deiglva ser ce acce Capital Lease Long term lease for satellite life (>1 yrs) Anchor Tenancy Indefeasible Right of Use (IRU) st g to the national Programmers resist O&M dollars for investment (termination liability, competitive annual priorities); Procurement dollars ineligible for these deals; Existing regulation is for 5 year max lease option NASA/NOAA ability to enter into multiyear contracts to serve Termination liability concerns; Statute limited to NASA/NOAA3 - AT&L offering changes; Cannot be used for as the anchor tenant for commercial space ventures. COMSAT unless approved by Congress Pays for up-front costs; signs agreements with others to get services and pays a large up-front fee, followed by annual Failed providers pulling out early; poor pricing methods charges for maintenance and upkeep Congress uncomfortable committing dollars beyond first year Multi-year contracts are limited to 5 years; Termination liability concern Multi-year/Long term lease Opportunity to reduce cost with longer leases Hosted Payloads DoD furnished payload; Pathfinder Long term solution with little time to solve near term budget issues and potential demand with the ongoing challenge Finding optimal approach to leverage COMSAT technologies; to accept large scale non-traditional approaches to satisfy long term solution requirements; acquisition, policy and legal concerns manifest risk special needs; short timeframe Timely ITU frequency coordination to bring service into use; current NTIA spectrum certification policy requires project funding prior to filing; adds significant delay to timeline; US launch vehicle requirement per Space Trans. Policy Figure 1-1: Defense Business Board - COMSAT Acquisition Approaches vehicles in place is unclear, and they likely vary from vendor to vendor. But, one could assume that the government is paying a premium for the flexibility of "indefinite quantity." Beyond the traditional immediate to year-long leases through IDIQ contracts, the DBB identified several non-traditional approaches, listed below in a table from the report [5, p.8]. Buy-to-lease, capital lease, anchor tenancy, and long-term strategies all run into the same political obstacles, namely that Congress will not commit to leases greater than 5 years due to "termination liability." As the law states, in the event the government terminates a contract, the government must reimburse the contractor for a substantial amount of unrecoverable costs for the planned services [11]. Indefeasible Right of Use utilizes a terrible incentive structure, with most of the cost paid for up front. Hosted payloads provide a great opportunity for saving on launch costs. However, aside from potentially conflicting launch vehicle requirements between agencies, this approach still requires unique satellites to be built, meaning high costs and long time horizons. The Defense Business Board ultimately recommended a near term aciton to take 17 advantage of long-term/ capital lease agreements. "By implementing commercial capital leases in multiple increments for up to 10-15 years to meet [needs], DoD could save up to $100M per year" [5, p.10]. This approach is not politically viable, and by committing to long-term contracts the government inherits tremendous liability risk. This thesis will suggest alternative solutions which are viable, cost-effective and less risky, by using optimal allocations of proven contract vehicles. 1.2 Conclusions from DBB Analysis An important takeaway is the current split in COMSATCOM agreements: 75% are one year leases and 25% are at "spot market" rates. This ratio will serve as a benchmark for qualifying model performance. Contract limits have an upper bound of five years, due to statutory restrictions. COMSAT "fill-rates" should be considered a source of uncertainty that can affect decision making. For example, if a consumer knows the possibility that supply may be extinguished for a given time period exists, the consumer will become more likely to purchase supply in advance of need, as it becomes available. Although this random variable is not included in the model, future extensible models should consider this. The Pathfinder initiative could provide valuable insight if new contract vehicles are actually evaluated. This thesis hopes to introduce a modeling framework which could be valuable in identifying theoretical contractual constructs which could then be used on a micro-scale in the Pathfinder program before being launched at the national level. 1.3 RAND - Wideband Investment Options In 2000, RAND published the most comprehensive public study on COMSAT acquisitions to date. The study focused on high-bandwidth (voice, video, data), minimally protected SATCOM. Motivation for the report stemmed from a growing demand for satellite communications and a lack of planned military owned capacity. RAND uti18 se - isid e sponmm -- ryaP raiO moDai ymin 14 . Prmybayw n l Suppay S 0 00 Figure 1-2: RAND Growth Projections lized the Advanced Military Satellite Communications Capstone Requirements Document. Gleaned from this document were two important implicit assumptions: military and political leaders do not want operations constrained by communications, and whatever bandwidth is necessary will be available [4, p. 7j. Furthermore, increased capacity was deemed necessary due to emerging military doctrine, such as UAV use, and "uncertainties posed by unknowable timing of future contingencies" [4, p.3j. RAND projected steady growth over the 2000-2010 time frame, across three types of demand: 1. Crisis Response - Additional capacity needed to respond up to two major theater wars or four small-scale contingencies 2. Daily military operations - Capacity needed for routine patrols, tactical intelli- gence and training 3. Day-to-day - Minimum capacity needed to ensure vital peacetime communica- tion The projects attempt to capture the trends at the time, but of course do not account for the variance inherent in demand. The illustration is simply useful for under19 standing the shortfall in military capacity for anticipated bandwidth and serves as motivation for investigating acquisition strategies. To satisfy the shortfall, the study considered the following investment options: " DoD-unique satellite purchase " Whole commercial satellite purchase " Fractional commercial satellite - transponder or fixed bandwidth lease " Communications service agreements [4, p. 20] The military typically makes acquisitions based on operational needs, and cost is only a criterion for differentiating among viable solutions, not the primary criteria. Thus, these options were evaluated against the criteria outlined in the Capstone Requirement Document: * Capacity - Is enough throughput provided? " Coverage - Are regions of interest covered? " Flexibility - Will multiple operation types and applications be supported? " Interoperability - Can the investment integrate with existing organizations and technology? * Access and Control - Will the option be available and accessible when and where needed? * Quality of Service - Will the option meet specifications for reliability, bit error rate and outage responsiveness? * Protection - Can the option survive attack and can it withstand jamming attempts? [4, p. 22] These criteria provide the basis for evaluating acquisition options and versions of the attributes that will be used in modeling. Capacity is more than sufficient in providing 20 DoD the necessary bandwidth. Commercial providers cover the same areas of interest where the military has concerns. To maximize flexibility, the use of both military and commercial systems is paramount. The Federal Communications Commission (FCC) has authorized certain frequencies bands within Ulta-high Frequency (UHF), X-band, and Ka-band as exclusive military use [4, p.18]. However, C and Ku bands have been authorized as commercial bands and the military can only operate within these bands on a strictly "noninterferance" basis, meaning DoD wholly owned systems cannot operate in these frequencies. If DoD wants to maximize flexibility, DoD must lease capacity on commercially owned satellites which operate in C and Ku [4, p.93]. Interoperability is largely a ground terminal configuration question, which this thesis will not address. Satellite purchases provide the greatest degree of access and control. Satellite orientation and beams can be reconfigured on the fly, whereas with leases the satellite bus will rarely be controllable; the military can only manage the transponders it leases. On COMSAT buses, spot beams could not be moved without permission of other users leasing capacity. Flexibility in this case could be enhanced by negotiating the ability to "reassign transponders rapidly between beams throughout the satellite coverage area" [4, p.63]. Quality of Service is not a factor in evaluating COMSAT contract vehicles as providers regularly maintain reliability well over 99%. For example, in 2008, TransCore, a logistics tracking company, announced its satellite network achieved 99.992% uptime in 2007 [8]. Protection is the one criteria important to military activities which COMSAT providers do not satisfy, and will not anytime soon. Security measures of any kind are costly in terms of both development time and expense. Thus, commercial providers build "minimally protected" satellites in the interest of time and money, as they are motivated by profits. Fortunately, the government could leverage the relatively less expensive unit price of commercial capacity to improve surviveability. If DoD leases some capacity on every satellite in a given region, the task of disrupting or jamming a military satellite becomes overly complex [4, p. 75]. Other security measures will be left to the experts. For this thesis, it will be assumed that the demand being satisfied 21 Figure 1-3: RAND Contingency Data accepts the protection risk. In addition to providing criteria for evaluating investment options, RAND identified key characteristics of the aforementioned types of military demand. RAND received US military contingency data from 1990-1997, pictured below [4, p. 100]. Contingencies with more than 100, but less than 5,000 troops were considered smallscale contingencies (SSC), between 5,000 and 15,000 troops were considered mediumscale, and between 5,000 and 45,000 were considered large-scale. On average, ten contingencies began each year, with 6.5 ongoing. Of the ongoing contingencies, 0.9 were large, 2.7 were medium and 2.9 were small. RAND estimated that any given time approximately 58,000 troops were deployed in contingencies. The median contingency duration was 3 months [4, p. 90]. Unfortunately, the study did not disclose the relative frequency on contingencies by region, but only reported global numbers. The important conclusions from this data is that much of the variance in military demand is derived from contingencies, and this concept presents three random variables of interest: contingency occurrence, contingency size given contingency occurred, and contingency duration given contingency occurred. A fourth random variable could be the decay rate of contingency size as the conflict dwindles. 22 1.4 RAND - Providers and Contracts Before comparing the investment vehicles, the COMSAT market, which negotiates trade of long and short term contracts, must be understood. Long term contracts, generally of durations one year or more, can be preemptible or nonpreemptible. Preemptible service can be taken from one user and given to another with higher priority, after a "notification period" which can vary between instantaneous to weeks depending on terms. Significant discounts are associated with preemptible capacity. On the other hand, a consumer could choose to buy additional levels of assurance, for a premium [4, p. 87]. Capacity not sold in the form of long term contracts is sold on the Ad Hoc Market, for duration periods less than one year and as short as one day. Ad hoc capacity is sold directly by satellite owners and can be resold by customers [4, p. 88]. Unfortunately, DoD does not resell capacity, even when it has excess, due to political limitations, though this option should be explored by policy makers. The market tends to dry up when war or natural disaster strikes, as one might expect, particularly over "thin routes," areas with few systems. This is what happened during the Gulf War '90-'91. In these instances, leaseholders sometimes have the provider sublet excess capacity [4, p. 89]. The prices in Table 1.1 reflect market rates in 1999, assuming a 3.6% discount rate and 4% annual declining price trend. Although the rates themselves are dated, the relative differences are still important for modeling trade-offs, and are likely persist over time. Despite their attractive Table 1.1: RAND - Lease Prices and Contract Duration Acquisition Method Price (Gbps-Year) Duration Transponder lease Transponder lease Transponder lease Transponder lease Satellite Purchase $274M $154M $77M $58M $48M 1 week 3 months 1 year 10 years 10 years steady-state appeal, purchasing satellites to cover all demand projections is not ideal for several reasons. This would limit flexibility as the military is only allowed to use 23 RANW~UN412 I I I. I I 700o 500 400 '00/1 .0.Purctagee-noY 200 100 0 0 1 2 3 4 5 6 7 8 reeit Purchae-6year ordsr-"O feitI oemm I.Yearleee No" 1O0"erl 9 10 11 12 13 14 15 16 17 18 Year 19 8OURCE RAND Ptgum S. 1Z-Ptmat Cost( IGbp aaPudon of Strategy and Year Figure 1-4: RAND - Effect of Delivery Lag on Sat Purchase certain frequencies, and would be excluded from strictly commercial bands (C-band). Demand is not steady state. It is highly variable and growing. Most significantly, there is a substantial lag-time between capital investment and return on that investment, in the form of lower marginal costs. The more current Defense Business Board analysis indicated that commercial satellites take more than 3 years and military satellite deliveries take longer than five. When the lag time on delivery is factored in, leases one year and longer are cheaper for the first ten years [4, p. 123]. Unless protection or other special characteristics are worth the discrepancy in price, satellite purchases are not economically viable, especially when considering the changing rate of technology. 1.5 Conclusions from RAND Study The RAND study provides several major insights. The first being criteria to grade investment options against, and also logical constraints for modeling satellite capacity acquisition. Assuming rising military satellite bandwidth demand, and realistic delivery times for satellite purchases, demand cannot be satisfied by satellite purchases 24 effectively without exorbitant costs and long lead times. A baseline for contract comparisons was also provided, and an step-wise linear equation was derived as an approximation. As noted earlier, current protocol has led to purchases of contract vehicles with durations that do not exceed 1 year. This may be due to providers requiring large upfront commitments. However, the RAND study shows that savings can be achieved with longer-term contracts, although diminishing after 1 year. These longer term contracts should be used to satisfy demand which is very likely to wane. For example, if demand in region 1 is fluctuates around 10 Gbps/year, then long term contracts should satisfy 1-2 Gbps/year, or some demand which is unlikely to be Furthermore, the growth rates in use described earlier, indicate a trend in desire for persistent global coverage. If one can reasonably expect the growth rates to remain positive for decade, long-term contracts should be invested in. The assumption could be validated by determining what global capacity is needed to have persistent coverage in all regions for "routine" tasks, and compare that number to actual global coverage by region. Assuming that committing to a longer-term contract will cost less, given US payment track record and that contractually obligated payments eliminate revenue risk on the provider-side, DISA should negotiate a payment schedule which does not provide an up-front cost, but rather slightly higher payments that yields the same NPV. The private sector is interested in immediate payment due to their risk profile associated with satisfying shareholder interests sooner rather than later. The desired payment schedule of the private-side indicates that the possibility of options contracts may be well received. 1.6 Emerging Technological Uses and Growth Many modern factors contribute to COMSAT growth worldwide in both the public and private domains. For worldwide consumers, demand has spiked for satellite television, internet and high definition broadcasting. For the US government, the 25 first important factor to be considered is the growth in UAVs, both domestically and abroad. In February 2012, Congress passed the FAA Reauthorization Act to enable the testing and commercial licensing of domestic drones by 2015. According to the FAA, as many as 30,000 drones could be patrolling the continental United States by 2020. [191. Undoubtedly, part of this surge will be used for border patrol in the increased fight against the "war on drugs" as the Defense Business Board report indicated. Other domestic uses will begin to surface in the coming years, as innovators in the domestic economy attempt to profit off the new regulations. For example, Amazon has announced Amazon Prime Air, a service which plans to deliver goods from its warehouses in thirty minutes or less utilizing Amazon UAVs. The company claims to be ready launch as soon as the FAA establishes governing rules, and is anticipating a 2015 launch [6]. 1.6.1 Demand Growth Within Contingencies In many contingencies similar to the ones examined by RAND, the US military has seen growth in satellite use per troop over recent years. Col Patrick Rayerman examined conflict usage data for recent Middle Eastern conflicts and found a relationship between Mbps per 5000 troops in conflicts over time. The graph below contains his published results [18]. Certainly this data alone would suggest increased satellite usage within the last decade. This data is normalized by conflict size. However, it is conceivable that conflicts in the future will require less personnel and may be won through strategic and technological superiority. Furthermore, recent political statements, executive orders and actions from the executive branch indicate a political shift to a "leaner force," focused on special operations [7]. This data should only be treated as a possible indicator of increased reliance on satellite communications. Trends in conflict size need to be measured. 26 Alctual and Projected 350- Mbps Used per 5,000 Military Members 300-W 250200- # T 150100- 0- Desert so 1990 4 Enduirlpna Freedom lrqi Freedom Noble Anv 1995 2000 2005 201 0 2015 2020 Figure 1-5: Mbps Used Per 5000 Troops 1.6.2 Global Demand Growth The demand RAND projected in 2000 has been realized. In 2010, Futron published its military segment forecast which showed realized demand in 2009. According to Futron, the US comprises an estimated 90% of the global military demand provided commercially [16]. This demonstrates that the growth was realized and still anticipated by industry experts in the future. Furthermore, the differences in projections by region illustrate that demand distributions can vary widely by region for any given time period. In addition to rising total usage, DoD also faces rising prices per unit bandwidth. In the graphic below, a prominent government contract vehicle, DSTS-G, is compared against the market average in Europe and the Middle East [9]. Transponder Equivalent (TPE) is simply a normalized metric for comparing bandwidth consumption, and typically represents 36 MHz of capacity [12]. The exact number of bits-per-second for a given TPE depends largely on the signal-to-noise ratio, which is a result of the technology used and physical distances. RAND explains that the achievable data rate depends on "waveform used, the effective isentropic radiated power (EIRP) of the satellite beam, and the size of the ground terminals used" [4, p.28]. Futron published a forecast on the average relationship between Mbps and TPE [14]. Understanding 27 . ......... . ........ - SuuVew fast A"M (%AI AsiaifA EtaMu AP SWibSahwAii Afrca JSSA SMifr Eail & Nortti Africa MI[NA fauMrfuropIEEUP MI E UI aW e oe n fEu r cipe( W Ef Il suum 6 Not"v Figure 1-6: F Amewa~ Amci.a C MAill De an PXrocl Figure 1-6: Futron COMSAT Demand Projection $2.5 $2.1 $2.2 $2.1 $2.0 $1.5 $1.0 2009 2008 2010 Fiscal Year m Europe and Middle East/Africa Market Average TPE Cost Europe and Middle East/Africa DSTS-G Average TPE Cost Source: FY 2010 Commercial Satelite Communicaions Usage Report Figure 1-7: Rising Government Contract Costs 28 iSAMI CNAM C North American Demand 2009 - 2019 2,500 0 0 9 2 140 120 2 100 ~1~ooo6040D 5W0 20 0 0 2009 2011 2013 2015 2017 2019 TPEs 4@9Mbps Source: Futron's 2010 Forecast of Global Satellite Services Demand Figure 1-8: Transponder Equivalent and Mbps the relationship between TPE and Mbps is important as different resources use both bits per second and Hz to compare bandwidth. In 2009, the ratio was roughly 57 kbps per TPE, based on the Futron graph. The Defense Information Systems Network (DISN) created the Satellite Transmis- sion Service-Global (STS-G) contract (DSTS-G) to leverage both long-term pricing advantages as well as options. Government contracts include both DSTS-G and NonDSTS-G. DSTS-G represents a 3-year contract with 7 one year options [2]. Thus, due to bulk purchasing, the contract should be less expensive than the average mar- ket rate. For the first time, DSTS-G surpassed the average market rate in 2010 [91. The reason for DSTS-G surpassing the market rate is due to differences in regional mix, as a larger portion of DoD capacity is focused in more constrained regions such as Europe and the Middle East. Thus, trade-offs between unit pricing by region is important to consider for planning purposes. An example of what differences could like is in the table below. This table is strictly for illustrative purposes. As there are many confounding variables. For example, although certain regions may be more expensive, it may be due to providers in the region, frequency bands employed, or combinations thereof. 29 Table 1.2: Example Regional Cost Comparison Middle East/Africa $M MHz $/Hz Rate/Avg. Avg ($/Hz) 300 3900 0.07692 0.805245871 0.09552744 North America Europe South America 120 100 1900 1500 0.06316 0.06667 0.661149241 0.69787975 20 180 0.11111 1.163132924 Asia North Africa Sub-saharan Africa 15 80 0.18750 1.96278681 20 250 0.08000 0.837455706 25 300 0.08333 0.872349693 A complete data set on all price points for all satellites, with all attributes, including provider, frequency, capacity, reliability and so forth should be maintained in order to separate effects on each component for modeling purposes. Spending not only varies across contract type, but also varies across frequency band. For FSS, the frequency bands employed are C, Ku, C-Ku (Crossband), Ka and X. Each band has a different frequency range and thus different attributes which allow for different applications. For example, C-band is used for television broadcasting and raw satellite feeds. It is also widely used in regions affected by heavy rainfall as it is less susceptible to "rainfade" (absorption of signal by atmospheric rain), than its popular counterpart Ku-band [3]. Thus, DoD is interested in utilizing all frequency bands for application access as well as redundancy to ensure reliability. The supply chart below, by band and vendor, illustrates realistic constraints in regions [13]. This reality makes price comparisons by vendor and operator also important. As previously mentioned, a full statistical analysis on a complete satellite data, or complete contract set, which includes attributes for frequency band, vendor and operator, should be performed for vendors and operators. The aforementioned factors, namely contract duration, region, capacity, frequency, and provider, serve as important attributes in modeling contractual decision-making. 1.7 Where the RAND model left off RAND's modeling efforts in 2000 utilized global demand projections, and examined the trade-offs between long and short term contracts without regard to regional differences or the inherent discrete nature of satellites. The analytical method they developed for determining optimal capacity is based on their expected cost equation 30 GEO COMMERCIAL FSS SATELLITE CAPACITY SUPPLY DISTRIBUTION 10/201 and Ku-band -ftw C-be r o"A'zj C-bsnd P. Ku-band KiU-band 04obnd I Ku-band Intelsat SES Telesat Eutelsat Other Figure 1-9: Futron - Supply Chart by Provider, Region and Frequency which is listed below [4, p. 137J: (x C = Pa +Ps j - a)f(x)dx " pa is the price of a * a is the amount of fixed capacity " p, is the spot market price * x is communications demand * f(x) is the distribution of demand x This may serve as a useful bounds in individual regions if extreme prices are used for Pa and p. However, this analytical method is not sufficient for determining how capacity should be allocated across satellites, and ultimately contract vehicles which must specify the satellite being used. 31 RAND concluded, where access and control and protection are not critically important to the mission, commercial assets can be leveraged to satisfy military demand and improve criteria related to flexibility, capacity, coverage and average cost. In terms of allocation strategy, the recommendation was "it may be more economical to make long-term commitments and 'waste' some capacity than to underestimate need and make up the shortfall with short-term contracts" [4, p.130]. With advances in computing power over the last decade, larger state spaces can be explored in real time for this type of decision making, and the universe of qualified satellites available should be investigated. The model presented establishes a framework for investigating contractual decisions with respect to time, satellites, regions, contract duration and other relevant variables. The research and projections presented demonstrate a need for satellite capacity planning to efficiently allocate tax-payer dollars. If careful capacity planning provides a method for the exploration of possible options and a solution or set of strategies that minimize expected expenditures while satisfying requirements, the cost savings can be spent elsewhere to maximize tax-payer benefit. 32 Chapter 2 Mathematical Formulation and DP Model 2.1 Integer Program Formulation Within this section, the mathematical formulation of the problem is discussed. 2.1.1 Parameters of Interest " A: Set of arcs. Each arc represents a set of contract decisions. The contract "decisions" are the chosen capacity levels across the set of satellites at a decision node. - as...s: Capacity level for each satellite on a given arc. - ca: Associated cost with set of satellite capacity levels, as a function of base cost and satellite parameters. - ba: Vector of bandwidth by region associated with each arc. For satellites which cover multiple regions, the bandwidth provided during the time period is divided equally among the regions covered. * ba,r: Bandwidth for region r from capacity levels in arc a. " S: Set of satellites. 33 - q,: The fixed maximum capacity of bandwidth, for satellite s. The satellite can be thought of as a vendor of bandwidth. r,: The set of regions satellite s covers. - M: Cost multiplier for satellite s, as a function of regions covered, satellite provider, and frequency type. * R: Set of regions. Each region realizes demand for each time step, which must be met. * D: Vector of realized demand by region. - dt: Realized demand for time period t. * dt,r: Realized demand for region r in time period t. * 1: Contract length, or duration, for each model instance. * T: Set of time periods. Each time period represents a "stage." 2.1.2 Decision Variables The decision variables are the arc choices at each time period. The set of decisions, from time period 0 to T, where T is the last time period, that satisfy the below constraints represent a solution. Va E At E T Ya,t 2.1.3 Objective Function Contract Costs: T min A I:Ca,tya,t t=O a=0 34 (2.1) 2.1.4 Constraints y is binary: Va c A, t c T Ya,t C 0, 1 (2.2) Only one decision per time period: Vt E T 1 Ya,t (2.3) a Decision lasts for contract period: Ya,t < Ya,t+1 ... Ya,t+l Va C A, t C T (2.4) Vr C Rit E T (2.5) State is feasible: 13 br,a,tya,t > dr,t a Satellite level is less than fixed satellite capacity: Va C A, s C S a. < q, (2.6) Satellite coverage is split evenly across its regions: ba, 2.2 2.2.1 - Va c A, s E S, r C R I (2.7) Dynamic Programming Solver Modeling Methodology Capacity planning over time for a given set of demand can be modeled effectively using a variety of methods. In particular, dynamic programming fits the problem well as the time dimension maps well to stages and the set of region capacity levels 35 maps well to states. 2.2.2 Stages, States, Nodes and Arcs In the DP solver, each stage is a time period. The time step between stages is 3 months, a convenient measure for comparing contracts along the steep part of the price function, those with durations between 0 and 12 months. The state in each stage consists of all the values of concern including: contract decision for the next period (capacity level on each satellite), cost, capacity coverage over each region, and predecessor. It is computationally straining to manage every integer combination of region capacity coverage. The nodes serve as a representation of granularity for the levels of coverage by region. For example, the first node in given stage corresponds to zero capacity coverage in all regions. The last node in a given stage (the last stage-node) corresponds to the highest region demand set by user input. The nodes in between depend on the level of granularity specified by the user. For example, if the maxRegionDemand is 18, and nRegLevels is 6, then each node in a given will represent a unique combination of capacities across all regions from 0 to 18 incremented by 3. Since the graph implementation utilizes adjacency arrays each node can be thought of as a single entry in the table below, where each column is actually managed as a separate array. e K: Set of nodes. Each node represents a set of capacity levels provided to the set of regions. The length of nodes is equal to "states" times "stages" plus two, for a source and sink node. - bn: Bandwidth for set of regions at each node n. This represents the minimum threshold for each state. It also acts as a way to set granularity of region-capacity levels investigated. * b,,: Region bandwidth for a given node. 36 - P: Vector of predecessor nodes, indexed by actual node. For example, if P6 equals 4, than the predecessor to node 6 is node 4, and an arc exists between the two. - 6: Vector of decision points, indexed by node. If a node is a decision point, contract decisions/ purchases can be made at that node. - X: Actual bandwidth supplied at each node. This differs from node- bandwidth, as "actual" can be greater than node-bandwidth. The actual bandwidth is the least expensive bandwidth achievable at each node, while satisfying all other constraints. In the event of a cost tie, the greatest bandwidth is kept. The re-labeling criteria is minimum cost, then maximum capacity. - k: Number of stage-nodes, or the number of states per stage. This constant provides indexing access by stage for an adjacency array implementation. Arcs represent contract decisions. All of the adjacency arrays stem from conversions on a vector of satellite levels. 2.2.3 Modeling Questions The questions this modeling effort seeks to answer are as follows: " Can a "test-bed" be created to compare contracts under varying assumptions? * Which types of contract decisions tend to perform better? " How can one compare relative value of satellites? 2.2.4 Model Assumptions Without knowing the breakdown of frequency and provider by region, it is impossible to separate the effects on price. With a totality of usage data, the effects could be separated to model new satellites and contracts. This thesis and associated model will assume an equal distribution of bands per region, and regions for each bandwidth 37 type. Military "demand" is what is deemed critical or required in subsequent periods. This may be due to contingency efforts or for routine observation or communication. The model makes decisions for FSS contracts. Satellites are in geosynchronous orbit, which is a common case for communication satellites. All contracts are nonpremptible. The market has enough liquidity to provide contracts at every decision stage. Satellites do not fail. The solver schedules contract purchases for Fixed Satellite Services (FSS). FSS describes service between geosynchronous satellites and fixed satellite antennae. Geosynchronous satellites orbiting over the equator at the same rate of Earth's rotation are in the same position relative to any landmass, and thus satellite dishes can remain in a "fixed" direction [12]. Historically, FSS has been the predominant architecture for SATCOM. However, increasingly DoD is investing in Mobile Satellite Services (MSS) due to emerging technology which can facilitate both uplink and downlink to FSS and MSS, across multiple frequencies, including L and S-band [171. Based on the historical aforementioned relationships that exist between price and contract duration, the step-wise approximation of the relationship is given below. Although the actual prices may fluctuate over time, the relative relationship between long and short term contracts is likely to be robust, unless risk profiles of the participants drastically change, or certain principles of time value of money change. The model assumes capacity available in any region exceeds demand and, for each region, one or more satellites provides coverage. Punit 243.2 - 14.7 * d if 0 < d < 12 77 ifd= 12 79.6 - 0.2 * d if 12 < d < 120 0 otherwise = 38 2.2.5 Tradeoffs Between Long and Short Term Contracts Aside from the price difference, utilization rates will vary by contract in a time period with non-constant demand. In general, utilization will always be better for short-term contracts. Put another way, utilization cannot be better for long-term contracts. Variance of demand drives the utilization rate of long-term contracts. If variance was zero, the long-term capacity could be perfectly predicted and utilization would be 1. If variance is greater than zero, utilization falls for a given demand that long term contracts must satisfy in all periods. Thus, when variance is small, long term contracts out perform short term contracts, and when variance is large short-term contracts can outperform long-term contracts for the same demand-periods. The extreme case illustrates this point. If you have a long term contract which covers 4 time periods, at price PL and short term contracts that follow demand perfectly at a much higher price at PS. Assuming both contracts cover all demand in the 4 periods, then the cost of long-term is: CL = QL * PL CS =(QL * Where UL) * PS Q is the number of units, P is the unit price per contract type and U is average utilization rate over the time period. Based on this illustrative relationship, cost of short term contracts for a given time period will be less expensive when UL < P. This is useful for getting a sense for when long or short term contracts should be used, and is useful for allocating portions of projected demand into contract vehicles. 2.2.6 Pseudo-code The pseudo code for the Dynamic Program constructor, buildSourceO, buildCenter(), buildSink, and backPath() functions are covered in Algorithms 1, 2, 3, 4, and 5. The actual source code is included in the appendix. 39 Algorithm 1 Dynamic Program - Contract Scheduler Constructor Initialize data structures and constants Create adjacency array structure procedure CONTRACTSCHEDULER(S, 1, D, maxRegDemand, regLevels) Get array of fixed satellite capacities satLevels +- matrix of sat level combinations for each level i in satLevels do for each satellite j do Get cost of satLeveli, level and add to satLeveli end for Get regionBWi for satLeveli end for regLevels <- matrix of region level combinations, from 0 .. .maxRegDemand > Stage nodes Calculate number of nodes Dimension adjacency arrays for: nodeCost a cost decisionPt > decision node boolean nodeSatBW > BW on ea sat at node nodeRegionBW > min Reg BW constraint at node actualBW > actual BW supplied (can be greater than nodeSatBW) predecessor > pointer to node in stage before end procedure 40 Algorithm 2 Dynamic Program - Build Source procedure BUILDSOURCE (ContractScheduler) Set source as decisionPt for each state in first time period do > first set of stageNodes if node is feasible given realized demand then for each possible satLevel (arc) do if satLevel is feasible then if Node has not been visited then Set nodeSatBW according to satLevel index Set nodeCost according to satLevel index Set actualBW according to satLevel index Set predecessor to source node if duration, 1, equals stage time increment then Set as decisionPt else Set intermediate nodes for contract duration Set last intermediate node as decisionPt end if else > node has been visited if satLevel cost < current cost then Re-label node and re-label intermediate nodes, if applicable end if end if end if end for end if end for end procedure 41 Algorithm 3 Dynamic Program - Build Center procedure BUILDCENTER(ContractScheduler) for each stage E T do for each node in stage do if predecessor exists then if node is feasible then for each node in next stage do if next-stage node is feasible then for each satLevel (arc) do if satLevel is feasible then if node has not been visited then Set nodeSatBW Set nodeCost Set actualBW Set predecessor if duration, 1,equals stage time increment then Set as decisionPt else Set intermediate nodes for contract duration Set last intermediate node as decisionPt end if > node has been visited else if satLevel cost < current cost then Re-label node Re-label intermediate nodes, if applicable end if end if end if end for end if end for end if end if end for end for end procedure 42 Algorithm 4 Dynamic Program - Build Sink procedure BUILDSINK (ContractScheduler) Get sink node for each node in last stage do if node has predecessor then if sink node has not been visited then Set sink nodeCost Set sink nodeSatBW Set sink nodeRegionBW Set sink actualBW Set predecessor else if nodeCost < sink nodeCost then Re-label end if end if end if end for end procedure Algorithm 5 Dynamic Program - Back Path procedure BACKPATH (ContractScheduler) Set last position in path to sink node for each stage, i, from last... 0 do Set pathi <- predecessor[pat hj±1 ] end for end procedure 43 E> Last node 2.3 DP Simulation - Adding Uncertainties The model specifies one type of uncertainty, demand, from two sources, as its generated from "regular " operations and a similarly specified distribution for "contingency" demand. The model assumes contingency demand to be sampled from an identical distribution as day-to-day demand, which is consistent with RAND's assessment of relative magnitude of contingencies relative to daily operations. Furthermore, the model assumes that if a contingency does occur, it lasts for two periods, or six months. After period 0, each subsequent day-to-day demand distribution incorporates a region-growth factor, to accurately portray expert forecasts of market behavior. After observing the importance of controlling for utilization, the military should be more open to long-term contracts, under the assumption that demand will grow for the foreseeable future. If the assumption holds, then utilization rates globally will tend to rise, making long-term contracts even more cost-effective. 2.3.1 Pseudo-code Algorithm 6 Distribution Generator Set Max Region Demand constant procedure GETDISTRIBUTIONS Inititalize random number generators and AbstractRealDistribution arrays Get vector of region types for all regions do if distribution type equals type index then if defaults enabled then Set preset values for dist type parameters else Get dist type parameters end if end if end for return Array of distributions of length |7I end procedure 44 Algorithm 7 Demand Generator procedure GETDEMAND(numPeriods, Distributions[] daily, Distributions[] contingency, numRuns, growth[], warProb[] ) Create array for active contingencies and three-dimensional demand array for each run do Create array for demand by period Create distribution array for growth in mean parameter for each period do Create new realized demand array for each region do if first period then Region distribution remains unchanged else Create new distribution with growth in mean parameter end if Sample from distribution while Sample is out of bounds do Re-sample end while if contingency is active then Decrement contingency duration counter if Counter equals zero then Set active contingency to false end if Sample from contingency demand distribution while Combined sample is out of bounds do Re-sample end while Add contingency sample to daily sample else Draw uniform random number between 0 to 1 if Draw is less than warProb then Sample from contingency demand distribution while Combined sample is out of bounds do Re-sample end while Add contingency sample to daily sample Set contingency to active Set duration to conflict duration end if end if end for Set demand for period end for Set demand for run end for return Demand for simulation 45 end procedure 2.4 Standalone Options In a similar fashion to purchasing fixed capacity in advance, options contracts for a fixed amount of capacity to be used for a certain time period could have a similar affect on cumulative costs. In many industries, it is common practice to purchase options contracts to limit downside risk, while consequently limiting upside potential (or cost savings) since this requires some fixed up front cost. In effect, an option purchasing strategy constrains variance on spending (or loss, or gains, depending on perspective). According to the Federal Acquisition Regulation 17.2 - Options, contracting officers may negotiate options contracts when "it is in the Government's interest," and (when using "sealed bidding") "there is a reasonable liklihood that the options will be exercised" [10]. Many additional provisions exist, but these two are first and foremost. Given that the plausibility of options contracts, they should be explored to examine their effects. Before incorporating options contracts in the model, logical pricing bounds must be determined. For pricing options the following parameters are significant: " p -unit price of bandwidth under fixed price contract " q - reservation price for one unit of capacity (contract price; the price for the right to buy) " e - exercise price for option (difference paid if right to buy is used) The following are assumed: p < q+ e p> q If p > q + e, the government would never buy fixed price capacity in the immediate term. If p < q, the government would never purchase options [15, p.30]. If a contract is to be purchased in time period t, and the option for this contract must be purchased one contract period in advance, t - d, then the unit price, p, 46 according to the step function aforementioned would be: {243.2 - 14.7 * 2d Punit if 0 < d < 12 With this in mind, the following relationships were established to capture the logical bounds, and a decreasing total cost, q + e, for higher, q, due to increased risk on the part of the buyer. The value of this risk is already represented in the step function which provides the buyer with a lower per unit cost if purchasing capacity in advance. However, what the options allow, is the ability to get longer term prices, without the constraint of purchasing capacity for each period in the contract. If the reservation price is zero, this describes a normal contract, without an option, purchased at time t. If the execution price is zero, then the reservation price must be equal to unit price of the contract purchased for two periods, at time t - d. The upper bounds for reservation price and execution price are described below: qupper 24 3.2 - 14.7 * r if 0 < r < 12 77 if r = 12 79.6-0.2*r if 12 < r < 120 0 otherwise 24 3.2 - 14.7 * d if 0 < d < 12 77 if d= 12 79 .6 - 0.2 * d if 12 < d < 120 0 otherwise = where r = 2d. eupper For a given reservation price, the base option execution price is: e=- eupper *q+epper qupper 47 The concept of buying options is very similar to purchasing fixed capacity in advance, but there exists another degree of flexibility which can be valuable when managing capacity over many sources of uncertainty as the government must do when accounting for many regions of demand. In essence, whatever reservation price is spent, that is the portion of satellite capacity purchased in advance, and the cost savings are proportional to q qupper times the difference between d and 2d baseline contract prices times satellite multiplier. Once an option price curve is negotiated between supplier and consumer, the question on the consumer side, is what reservation price and how many contracts to purchase. It may be conceivable, that depending on calculated usage probabilities, some contracts will be purchased with high reservation prices (those likely to be used), and some with low reservation prices (those less likely to be used). This also largely depends on risk tolerances. 48 Chapter 3 Results 3.1 Small Deterministic Example To illustrate the complexities and trade-offs of satellite capacity planning, a small scale example is presented with results. Below are the parameters for a 2 satellite, 3 region problem. * Satellite 0: - O = 10 - ro {0, 1} - mo = 1.1 * Satellite 1: - qi 3.1.1 10 - r = {1, 2} - m =1.0 Deterministic Results The optimal the allocation of bandwidth for each satellite, across different contract durations, for the same demand, is not intuitive. 49 .. . . ............. ...... -- 1 ......... ........ .. .. SatLevels 12-mo Contracts 40 730 -o 41 -~20 10 0 5 10 15 20 25 Time Period (3mo) + sat 25 +- sat 26 Htghthartls co, Figure 3-1: Two Satellite, Three Region, Twelve Mo. Contract Results SatLevels 6-mo Contracts 40 30 .L 20 _J 10 0 0 5 10 15 Time Period (3mo) Ssat 25 20 25 -- sat 261 H~ghcharts m Figure 3-2: Two Satellite, Three Region, Six Mo. Contract Results The solutions pictured above represent the least expensive set of contracting decisions, for a type of contract, for given set of realized demands. These solutions also represent the decisions for maximum utilization of each contract type for a given starting period. Alone, these results only illustrate the best one can do for a given set of demand, and if forced to use only one type of contract. These do however provide bounds on what can be achieved with the given contracts. Looking at the Figure 3-5, one might infer incorrectly that just buying long-term contracts is the answer to satellite capacity planning. The above results demonstrate 50 SatLevels 3-mo Contracts 40 30 20 10 i0 0 5 15 10 20 25 Time Period (3mo) -sat25 *-sat26 Figure 3-3: Two Satellite, Three Region, Three Mo. Contract Results Bandwidth and Demand for Region 1 20 10 5 0 10 5 0 15 20 25 Time Period (3mo) + Bandwidth for 12-mo contracts + Bandwidth for 6-mo contracts * Bandwidth for 3-mo contracts +A- Demand Figure 3-4: BW Provided by Contract and Demanded in Region 1 Cumulative Cost of Run 300k 200k 10. 0 ........ Ok 0 S 15 10 20 25 Time Period (3mo) - Cumulative Cost for 12-mo contracts a- Cumulative Cost for 3-mo contracts -- Cumulative Cost for 6-mo contracts Figure 3-5: Cumulative Cost by Contract of a run 51 Cumulative Cost of Run 200k 150k 100k 5ok 014 50k 0 5 10 15 Time Period (3mo) 20 25 + Cumulative Cost for 12-mo contracts - Cumulative Cost for 6-mo contracts m Cumulative Cost for 3-mo contracts -* Cumulative Cost for Fixed 1+3-mo contracts Cumulative Cost for Fixed2+3-mo contracts - Cumulative Cost for Fixed3+3-mo contracts Figure 3-6: Cumulative Costs with Fixed Capacity Contract Types one example of the "best fit" of contracts for a given set of demand, and utilization is maximized for each contract type. The results below show what different strategies return on another set of randomly generated data. Fixed1 represents purchasing 5 units of bandwidth on each satellite for all periods, and 3 mo contracts for all demand not covered. Fixed2 represents purchasing 8 units of bandwidth on each satellite for all periods, and 3 mo contracts for all demand not covered. Fixed3 represents purchasing 11 units of bandwidth on each satellite for all periods, and 3 month contracts for all demand not covered. This shows that there are possibly diminishing returns on buying fixed capacity, as utilization goes down, as does cost effectiveness, with bulk purchasing for this set of demand. The average utilization rates can be seen in the table below. Table 3.1: Average Utilization for All Regions 6 mo 3 mo Fixed1 Fixed2 Fixed3 12 mo 0.4301 0.4624 0.5400 0.5210 52 0.4539 0.3977 Bandwidth and Demand for Region 1 15 10 ~0 5 0 5 10 15 20 25 Time Period (3mo) -+- Bandwidth for 12-mo contracts + Bandwidth for 6-mo contracts -a-Bandwidth for 3-mo contracts -*- Demand - Bandwidth for Fixed1+3-mo contracts -0+Bandwidth for Fixed2+3-mo contracts -+ Bandwidth for Fixed3+3-mo contracts Figure 3-7: BW Supplied and Demand for Region 1 With Multiple Contract Types 3.2 Results with Options Contracts Purchasing options contracts and purchasing fixed capacity in advance represent different levels of commitment. As a result, the potential savings vary in proportion to the commitment, as do the downside losses. Buying an option contract is akin to purchasing a small portion of fixed capacity in advance. This is due to the bounds placed on q + e. Pictured in Figure 3-8 is a representative effect of options contracts. This particular level of options contracts purchased in advance just slightly outperforms the "immediate term" contracts. However, similar to the fixed capacity results, for a given set of demand distributions, there exists an optimal strategy which yields the lowest cost expectation. One strategy to find this level would be to increase the options level on each satellite, until a direction reversal is detected in the cost expectation of one thousand runs. 3.3 Results with Multiple Runs Simulation parameters: * 2 satellites * 3 regions 53 Cumulative Cost of Run 250k 200k 150k 0 50K Ok 50k 0 5 15 10 20 25 Time Period (3mo) - Cumulative Cost for 12-mo contracts Cumulative Cost for 6-mo contracts r* Cumulative Cost for 3-mo contracts + Cumulative Cost for Fixed +3-mo contracts -- Cumulative Cost for Fixed2+3-mo contracts +- Cumulative Cost for Fixed3+3-mo contracts Cumulative Cost for Options1+3mo Contracts Figure 3-8: Single Run With Options Contract - normal demand distribution (Af(5, 2)) - normal contingency demand distribution (AP(5, 2)) - maxRegDemand = 20 - contingencyDuration= 2 - growth = 1.01, 1.012, 1.005 - warProb = .05, .01, .01 * 30 periods * 6 contract types * 30 runs for each contract Satellite 53 has a negative skew in all like cases, relative to satellite 54, indicating it tends to be more preferred in the minimum cost solutions. This may indicate that capacity on satellite 53 should have a priority in acquisition for all overlapping areas covered jointly by satellite 53 and 54. This behavior is also a result of the relative price differences, distribution shapes of demand and growth in regions covered. The Figure 3-11 shows another simulation with 9 contract types, including three 54 .. ........ Cost Histogram to 3MO C ntract Costs FIXed2+3rn Curve 12mo Contract Camt 6MO Contrat Costs - oxed3+3mno Curve FRxed I+ Contract Costs Fxhd2 +Contraco Costs Fixed3 + Contwat Costs -- 3mo Cumv 6mo Curve -12aw Cumv - fxed1+3mo cut" Figure 3-9: Cost Histogram by Contract for Two Sat, Three Reg Figure 3-90:CostlitHistgra 700 by Contract rToST SatI> lHistogram hreee o0 Soo 4010 200 100 53 12 MO sat 53 6 ma 3 ="Curve SSat S- sat s54 saw 53 3mo-sat S3 12 mo Curv F r - - sat 53 6 moCurve sa 53 3 mo Cumv te ----- Lr 55 saw 54 12 mo sam 54 6 mo sat S4 3 iss- saw 54 12 mo Curve -- sat 54 6 too Curve Cost Histogram 2 3OMoosts FxO + 3ds+M Cost Fixodl oMCosts Fixed2 6moConracttCosts 12mo Contract Costs 5moContract Cot Unlto Cum -FIed1.3to Curve - F~xed2 3mo Curv - Roa3+3ro Crve - Optionsl + 3 Mo Costs 3moCurve oCurve 0optnos, +3Mo Costs Optm2 + 3 MaCosts Opto - 3 MoCosts -ptoos 3+ 3 MoCosts Options3 + 3MoCots Figure 3-11: Cost Histogram - Nine Contract Types Cumulative Cost of Run 250k 200k 150k 0 100k 50k Ok -50k 0 5 10 15 Time Period (3mo) 20 25 + Cumulative Cost for 12-mo contracts - Cumulative Cost for 6-mo contracts Cost for 3-mo contracts -+- Cumulative Cost for Fixedl+3-mo contracts Cost for Fixed2+3-mo contracts + Cumulative Cost for Fixed3+3-mo contracts Cumulative Cost for Optlons1+3mo Contracts -w Cumulative Cost for Optlons2+3m Contracts * Cumulative Cost for Options3+3mo Contracts -a- Cumulative - Cumulative -+ Htqh lar%or Figure 3-12: Cumulative Cost - Nine Contract Types different options strategies. The curves for all three options strategies overlap due to the small differences in cost between each strategy and a lack of granularity at the binning in the histogram. The figure 3-12 shows how slightly the results vary by option contract on a given run. This is due to the default reservation price being very small, and thus any realized savings will be small. But, the risk of not utilizing an options contract drops, if normalized by cost. The parameters to experiment with would be reservation price and number of contracts purchased in advance. 56 3.4 Time Complexity This problem grows in multiple dimensions. State space grows as one of the following increases: " Granularity / Region Levels increases, thereby increasing number of nodes per stage. * Number of regions increases, increasing number of nodes per stage. * Number of time periods grows, increasing number of stages, and thus the total number of nodes. " Adding detail to the node states. For example, if a node represents frequency band, by region, instead of blanket region demand, the number of nodes increases for the same level of granularity. * Adding satellites increases the number of arcs or possible decisions, but does not increase nodes. To examine the time complexity of this dynamic programming formulation, the number of steps required to solve each problem is approximated with a counter which tallies visits and re-labels at nodes. The number of steps approximations is totaled for an increasing number of arcs, holding nodes constant, and an increasing number of nodes, holding arcs constant. The Figure 3-13 shows a linear relationship between nodes in the DP graph and number of steps required to solve. The number of steps is an approximation which counts the number of nodes labeled or re-labeled. This excludes pre-processing time and does not count in feasible arcs which are still looped through. For this figure, satellites were held constant at two. 3.4.1 Leading Indicator As mentioned in Section 2.2.5, there seems to exist a strong relationship between utilization and cost effectiveness of contracts. Using rough approximations for price 57 Number of Steps to Nodes 25000 y= 0.2132x + 586.73 R'= 0.94809 20000 15000 4 E S10000 number steps -Linear (number steps) 0 0 10000 20000 30000 40000 50000 60000 70000 80000 90000 100000 Number of Nodes Figure 3-13: Number of Steps to Nodes of contract (independent of which satellite is being used), averageprice/utilization yields a good ranking metric for cost performance. In the example provided by Figure 3-12, the six contracts in the table perform in the same order as the simple metric dictates. This is important because for certain contracts payment may occur after the period is over. Costs may not be realized until payment. utilization (amount used on satellite / If real time amount owned on satellite, for all satellites under contract) can be maintained or approximated, then certain contracts may be modified mid-period to account for changing trends, where utilization is spiking or diving. Table 3.2: Utilization as Precursor to Spending 12 mo 6 mo 3 mo Fixedi Avg Price / Utili zation Rank on Metric Actual Rank 3.4.2 161.5786 1 1 336.6633 5 5 366.1078 6 6 176.5948 4 4 Fixed2 Fixed3 143.2822 2 2 157.0599 3 3 Adding Detail without Adding Time It is possible to consider a more detailed state space, while having a minimal impact on solve time. For example, consider adding a frequency-level constraint to each re58 gion. Regions 1 to R must clear a threshold for C-, Ka- and Ku- bands, in addition to all other constraints. One could add to the nodes directly, storing frequency specific levels for each region. But this would cause the number of nodes to increase, since the number of possible combinations of region-frequency-levels is greater than the number of possible combinations of region-levels, assuming the same delimiter for granularity at each node. Rather than add directly to the node, one can add information about a node or arc by expanding the use adjacency arrays. In the constructor of the problem, a frequency array can be created alongside the satellite-level arc array, in which the frequency level at index i corresponds with the satellite level combination at index i. This will allow for easy pruning at each stage by frequency constraints without adding to the number of nodes. The only additional time consumed by node creation is O(a) in pre-processing, where a is the number of arcs. In the current formulation, time complexity is a function of live nodes above the lower demand constraint. The upper bound is an arbitrary maxRegDemand value that is some value above demand level the user cares about. Since the dynamic program solver runs after realizing the demand, the upper bound should be determined for each run as the next viable node above the highest realized demand vector in a given period. There is a trade-off in pre-processing time if this is to be done for each run, as a new ContractScheduler object would need to be instantiated. Two options to consider would be a new instance of the solver for each run with lowest viable node for all periods as the upper bound, or the lowest viable node for all periods for all runs with one instance of the solver. Time can also be saved with an early break from the arc assignment loop. If the contract decisions (arcs) are properly sorted, in relation to the loop which iterates over all arcs, it could be possible to determine if all arcs following a certain arc are more expensive. For example, if the satellites are sorted by price multiple, then [0,11 will always be cheaper than [1,0], and marginal capacity on the cheaper satellite will be preferred to satisfy demand in regions serviced by both satellites. 59 3.4.3 An Alternative Representation When certain conditions are met, node representation can be altered to save on time complexity. If regional combinations exceed satellite level combinations, the nodes should be represented as "satellite levels" rather than "region levels." The arcs would remain unchanged, but an adjacency array for region demand would be created, similar to the existing actualBW array. 60 Chapter 4 Conclusions 4.1 Thesis Conclusions This thesis concludes that DoD should reevaluate its use of longer term contract vehicles, such as the DSTS-G contract. Fixed capacity should be purchased in advance. Two questions remain: how much fixed capacity should be purchased, and on which satellites? This model serves as a basis to answer those questions. With the proper parameters, both questions could be answered, as the results show. The government and its decision makers need a "testing" environment for approximating how contracts will preform in a changing fiscal and political environment. Potential contract constructs need to be tested before being deployed. Satellites need to be pruned, as well as model satellites with new attribute combinations. This model provides such capabilities. Furthermore, the model provides the mechanism for testing the provision, reasonable likelihood, for options contracts. The dynamic program presented could be a sub-problem to a larger optimization algorithm which solves this problem over many iterations across different uncertainty sets, which may encompass many expert opinions of reasonable combinations of distribution type and growth parameters. Certainly such a large optimization problem will be slow, as it currently stands. The sub-problem DP algorithm needs to revisited and improved upon for maximum efficiency. DoD should consider making the bulk of its contractual decisions at regular in61 tervals. It is unrealistic to suggest that all contract decisions could be made at regular time stages, as this paper discusses the irregularity inherent in contingencies, but making regular larger, long-term purchases could be valuable. This would allow modeling of the process to better represent reality. More importantly, measurement and evaluation from period to period could be standardized and more easily assessed. For example, it is much easier to compare a budget overshoot in one 6 month period to a budget undershoot in following 6 month period, than it would be comparing decisions made across 4 weeks followed by 2 weeks of performance after another round of bandwidth purchases. Perhaps most importantly, data collection could become a regular exercise and could be more consistent. The government should work on developing heuristics for when variance is too high to consider long term fixed capacity contracts in advance. Lastly, the use utilization as a proxy for cost, if its values are determined at known at different times from actual realized cost, could be useful for guiding tactical contractual decision making. 4.2 Future Work and Potential Uses The biggest issue seems to be data collection. Data is inconsistent from report to report, and accounting for both bandwidth and expenditures is flawed. The first thing SMC or the like should accomplish is a thorough enumeration of every COMSAT contract with corresponding costs and bandwidths and service types explained. As yearly cash outflows for certain projects may happen at irregular times, capacity utilization and contract type by satellite for all contracts should be regularly maintained. With price approximations and utilization rates, cost estimates can be updated with usage reports which may be maintained daily, hourly or minutely. This may be useful for projecting where costs are heading by satellite or region before year or quarter end. This type of model is ideally suited for evaluation of contract performance. Once empirical usage reports become available, contracts of all types can be compared to gauge historical performance, as well as theoretical performance if certain assets were 62 used in different areas, or by different DoD agencies. Mobile Satellite Services(MSS) represent a significant and increasing contribution to total expenditures. Orbits would have to be modeled to include coverage areas during discretized time periods, using software such as STK. Additional contract types should be incorporated into the model, including the trade-offs between leasing capacity directly and end-to-end solutions, in terms of cost and lag time. Additional constraints should be included for orbital slots, "friendly governments," interaction between available supply and price and frequency constraints. Additional sources of uncertainty should be incorporated including: satellite capacity availability, and satellite region-coverage. This model may be useful for determining relative value of satellites approaching "end-of-life." Attributes associated with most valuable satellites for projected future can be used to rank existing military systems. Those systems with the best projected value that are approaching end-of-life can be prioritized for upgrade or replacement. 63 64 Appendix A DP Code - Java A.1 Contract Scheduler import java.util.ArrayList; import java.util.Arrays; import org.apache.commons.math3.distribution.AbstractRealDistribution; public class ContractScheduler private int private Satellite[] private int private double [] [] private int endTime; nbrRegions; { numberSteps; satellites; nbrSatellites; demand; private int private int[] private int private int H] private double[] private double[][] regBWFromSatLevel private double[][] actualBW; private int private int private int private int duration; private int nodes; private double[] private int H H private int [] ] nodeRegionBW; private int[] private boolean[] decisionpt; private boolean[] decisionStage; path; totalCost; [ satLevels ; satLevelCost; / 1, maxRegionDemand; nRegLevels; regLevels [] [I i, t r; 1 nodeCost; nodeSatBW ; pred; %I 65 int private stageNodes; double[] optionsContractCosts; double[] optionsReservationCosts; double[] optionsExecutionCosts; int[][] optionsExecuted; int[][] excessSatLevels; double [] excessCost; double [][] boolean[] optionsAndExcessCost; optionReservationStages; double [][] optionsUpperBounds; double totalOptionsCost; double[] cumulativeOptionsCost; double [] cumulativeCostWithOptions; public ContractScheduler(Satellite[] s, in t dur, double [][] d, int maxRegD, int regDLevels) numberSteps=0; nRegLevels = regDLevels; maxRegionDemand = maxRegD; = duration dur; satellites = s; demand = d; endTime = demand.length; nbrRegions = demand[0].length; nbrSatellites = satellites.length; path = new int[endTime+1]; int satLevelComb for (Satellite 1; = sat : satLevels [] n intt] for Nr = new double [satLevelComb]; = new = (sat.getCapacity(+), new int[satLevelComb][satellites.length]; = satLevelCost int { satellites) satLevelComb *= int[satellites.length]; new int [satellites.length]; (int i=0; i<Nr.length;i++){ Nr[i]=satellites[i].getCapacity(); regBWFromSatLevel = new double [satLevels.length] [nbrRegions]; satLevels = getCombinationsMatrix(n, Nr); for (int i=0; i<satLevels.length;i++){ satLevelCost[i]=0; for(int j=0; j<satLevels[i] length; j++) { satLevelCost[i]+=satellites[j].getPrice(satLevelsti][j], } regBWFromSatLevel[i]= int[] n2 = int[] Nr2 = new new convertToRegBW(satLevels[i]); int[nbrRegions]; int[nbrRegions]; int regLevelComb=l; 66 duration); { for (int i=0; i<Nr2.length;i++) { Nr2[i]=nRegLevels; regLevelComb*=(nRegLevels+1); } regLevels = new regLevels = getCombinationsMatrix(n2, Nr2); int int[regLevelComb][nbrRegions]; demandMultiplier = maxRegionDemand System.out.println("nRegLevels: for(int i =0; for "+nRegLevels+",anddemandMultiplior: i<regLevels.length; (int nRegLevels; / j=0; { i++) j<nbrRegions; j++) { regLevels[i][j]*=demandMultiplier; nodes (regLevels.length)*(endTime) = nodeCost new = decisionPt for(int double[nodes]; new = boolean[nodes]; i<decisionPt.length; i=0; 2; + i++) { decisionPt[i]=false; nodeSatBW new = int[nodes][nbrSatellites]; nodeRegionBW new int[nodesi[nbrRegions]; actualBW new double[nodesl[nbrRegions); int = counter for (int 0; node=1; node <nodeRegionBW .length; nodeRegionBW[node]= node++) regLevels[counter]; counter++; if (counter == (regLevels.length)) { counter=0; decisionStage= for(int i =0; new boolean[demand.length+l]; <decisionStage.length; i i++) decisionStage(i]=false; I pred for = new (int int[nodes]; i =0; predii] i < = nodes; i++) -1; } stageNodes = regLevels.length; } public void csd() { buildSource (); 67 { { "+demandMultiplier) buildCenter (); buildSink(); backPath(); I private void buildSource() { nodeCost[0]= 0; for (int i =0; i<satellites.length; i++) { nodeSatBW[0][i]=0; I for (int i=0; i<nbrRegions; i++) { nodeRegionBW[0][i]= 0; I decisionPt [0]=true; for (int i =1 int if ; i<stageNodes+1; toNode ( = i++) { i; isFeasibleNode(nodeRegionBW[i], for (int satLev=0; if satLev++) (isFeasibleLevel(regBWFromSatLevel[satLev], if { demand[i/(stageNodes+1)])) satLev<satLevels.length; (pred(toNode]==-1) { AL AV/f nodeRegionBW[i])) { { numberSteps++; nodeSatBW toNode=satLevels[satLev]; nodeCost[toNode]=satLevelCost[satLev]; actualBW[toNode]=regBWFromSatLevel [satLev] pred[toNode]=0; if(duration/3 ==1) { decisionPt[toNode]=true; else{ setIntermediateNodes(toNode , satLevels[satLev], nodeCost[toNode], regBWFromSatLevel[satLev]); } } else if (satLevelCost [satLev] < nodeSatBW [toNode] nodeCost [toNode] nodeCost [toNode]) { satLevels [satLev] satLevelCost [satLev] setIntermediateNodes(toNode , satLevels[satLev], nodeCost[toNode], regBWFromSatLevel[satLev]); numberSteps++; } } 68 private void for { buildCenter() (int stage=1; for(int stage<endTime; node= stage++) { (stage -1)*stageNodes+1; if(pred[node] stage*stageNodes; node++) { { if(decisionPt[node]) if node<= { 0) >= ( isFeasibleNode(nodeRegionBW[node], demand[node/(stageNodes { +1)])) if( stage < endTime) int nextStage for(int toNode<= nextStage*stageNodes; toNode++) toNode= stage+1; (nextStage -1)*stageNodes+1; { if demandltoNode/(stageNodes+1)])) = (isFeasibleNode(nodeRegionBW[toNodel, { for (int satLev=0; if regBWFromSatLevel[satLev], nodeRegionBW[toNode])) (isFeasibleLevel( { if ]==-1) satLev< { satLev++) satLevels.length; (pred[toNode { nodeSatBW [toNode]=satLevels[satLev]; nodeCost[ toNode]=satLevelCost[satLev]; actualBW[ toNode]=regBWFromSatLevel[satLev]; pred[ toNode]=node; numberSteps if duration/3==1) ( { decisionPt [toNode]=true; else { setIntermediateNodes (toNode , satLevels[satLev], nodeCost[toNode], regBWFromSatLevel[satLev]); } else { if satLevelCost[satLev] < ( nodeCost[toNode]) nodeSatBW (toNode] = satLevels[satLev]; [toNode] = satLevelCost[satLev]; nodeCost actualBW [toNode]= regBWFromSatLevel[satLev]; setIntermediateNodes (toNode , satLevels[satLev], nodeCost [toNode], regBWFromSatLevel[satLev]); numberSteps 69 } } private void buildSink() { int stage=endTime; int sinkNode = endTime*stageNodes+1; if node<= stage*stageNodes; (stage -1)*stageNodes+1; for(int node = node++) { (pred[node]>= 0) { if ( isFeasibleNode(nodeRegionBW[node], if(pred[sinkNode]==-1) demand[node/(stageNodes+l)])) { nodeCost[sinkNode]=nodeCost[node]; nodeSatBW[sinkNode]=nodeSatBW[node]; nodeRegionBW[sinkNode]=nodeRegionBW[node]; actualBW[sinkNode]=actualBW[node]; pred[sinkNode]=node; numberSteps++; } (nodeCost[node] < nodeCost[sinkNodel){ if else nodeCost[sinkNode]=nodeCost[node]; nodeSatBW[sinkNode]=nodeSatBW[node]; nodeRegionBW[sinkNode]=nodeRegionBW[node]; actualBW[sinkNode]=actualBW[node]; pred[sinkNode]=node; numberSteps++; } } } } } public void backPath() { path[endTime]=(endTime)*stageNodes + 1; System.out.println(path[endTime]); for (int stage = endTime-1; stage>=0; stage--) { if(path[stage+1]!= -1) { path[stage] = pred[path[stage+1]]; System.out.println(path[stage]); } else { System . out . println (" Predeccessoruisabeyonduroot } public void outputDecisions() for(int stage=0; { stage < endTime; stage++){ 70 onabackupath!") { if != (path[stage] { -1) totalCost+=nodeCost[path[stage]]; System. out. println("Stage for(int i=0; :"+stage); ( "Cumulat iVe cost System. out. printin i<nodeSatBW[0].length; "+totalCost) i++){ System.out.println("Satellite :e"+i+",Leve1: "+nodeSatBW[path[stage]][i]); } System.out.println("ActualBW supplied:,"+Arrays.toString(actualBW[path[stage]])) } { else System. out. print(" Cannot print.results f orBW on,,nonex ist antpathinode \n) } } } public boolean for isFeasibleNode(int[] (int i=0; if( nodeBW, i<nodeBW.length; (nodeBW[i]+0.0 return double[] i++) -d[i]) { d) { < 0.0000001) { false; } } return true; } public boolean for(int isFeasibleLevel(double[] i=0; convertedRegBW, i<demand.length;i++) if(convertedRegBW[i] return demand[i] - int[] demand) { { < { 0.0000001) false; } } return true; } public void set IntermediateNodes (int to, int[] satLvl, double cost, double [] regBW) { int predecessor = to; for(int stage=1; stage < duration/3; if(to+stage*stageNodes < stage++) { nodes) { if(isFeasibleNode (nodeRegionBW(to+stage /(stageNodes+1)])) e {t', so d , ,, t t * i, , stageNodes], , nodeSatBW[to+stage*stageNodes] actualBW[to+stage*stageNodes] = satLvl; = regBW; nodeCost[to+stage*stageNodes]= cost; pred[to+stage*stageNodes] = predecessor; numberSteps++; predecessor+=stageNodes; if (stage== ((duration/3) -1)) { decisionPt[to+stage*stageNodes] = } } else { break; 71 true; demand[(to+stage*stageNodes) } satCapOwned) { convertToRegBW(int[] public double[] double[] regBW = new double(nbrRegions]; for i=0; i<nbrRegions; i++) { (int s=0; s<satCapOwned.length; s++) { for (int (int r for { satellites[s).getRegions() : if(r==i) { satCapOwned[s] regBW[i]+= / (satellites[s].getRegions().length +0.0); } } } regBW; return public void static if (idx == getPermutations(int [I n, int ] Nr, n.length) { idx, ArrayList<ArrayList<Integer>> ch, U- ArrayList<Integer>() i++) i=0; i<n.length; for(int th n new w ArrayList<Integer> int { w.add(n[i]); I combs.add(w); return; } for i = (int <= i 0; n(idx] = getPermutations(n, public i++) Nr[idx]; Nr, idx+1, n, getCombinationsMatrix(int[] int [I] { i; combs); int [ Nr) { int levels=1; for(int i=0; i<Nr.length; i++) { levels*=(Nr[i]+1); I int[]f] combMatrix = new int[levels][n.length]; ArrayList<ArrayList<Integer>> int idx = getPermutations(n, Nr, idx, for(int combs = new ArrayList<ArrayList<Integer>>); 0; i=0; i for(int combs); <combMatrix.length;i++){ j=0; j<combMatrix[0].length; j++){ combMatrix[i][j] = combs.get(i).get(j); return combMatrix; public getSats() Satellite[] { return satellites; } public double [][ return public intt] getDemand() { demand; getPatho { 72 combs) { return path; public double[] getNodeCost() { return nodeCost; } public int[][] getNodeSatBW() { return nodeSatBW; I public doublef[][] return getActualBW() actualBW; I public int { getDuration() return duration; I public boolean[] getDecisionStages() { return decisionStage; I public boolean[] return getDecisionPts() { decisionPt; } public int { getStageNodes() return stageNodes; I public void getOptionsCost(int[] optionsPurchasedSatPer, double reservationPer, int duration) { setDecisionStageso; cumulativeOptionsCost = new double[demand.lengthl; cumulativeCostWithOptions double[] new double[demand.length]; = optionsBase=Satellite.getOptionsBase(reservationPer, duration); optionsContractCosts = new double[demand.length]; optionsReservationCosts=new double[satellites.length]; optionsExecutionCosts = new double[satellites.length]; optionsUpperBounds for(int = new double[satellites.length][2]; i=0; i< optionsExecutionCosts.length; i++) { optionsExecutionCosts[i]=optionsBase [1]*satellites[i].getSatPriceMult(; optionsReservationCosts[i]=optionsBase [0]*satellites[i].getSatPriceMult(; optionsUpperBounds i] [0]=optionsBase [21* satellites optionsExecuted= excessSatLevels new = new getSatPriceMult (i] optionsUpperBounds Ci] [1]=optionsBase [3] *satellites ); i]. getSatPriceMult () int[demand.length][satellites.length]; int[demand.length][satellites.length]; for(int per=O; per<demand.length; if(decisionStage[per]) per++) { { for(int sat=O; sat<satellites.length; sat++) { int diff = nodeSatBW[path[per]] [sat] - if(diff>O) optionsPurchasedSatPer[sat]; { excessSatLevels[per][sat]=diff; optionsExecuted[per][sat]=optionsPurchasedSatPer[sat]; } else if (diff < 0){ 73 optionsExecuted[per][sat]= int diff2 nodeSatBW[path[per]][sat]; = nodeSatBW[path[per]][sat]-optionsExecuted[per][sat]; excessSatLevels[per][sat]=diff2; } else { excessSatLevels[per][sat]=0; optionsExecuted[per][sat]=optionsPurchasedSatPer[sat]; } } } else { optionsExecuted[per]=new int[satellites.length]; r pt, zero! n1 excessSatLevels [per]=nodeSatBW[path [per)]; } } double cum0ptionsC=O; for(int i =0; i< optionsContractCosts.length; double i++) { sumSatContracts=O; if(decisionStage[i]==true) for(int { sat=0; sat<optionsPurchasedSatPer.length; double satContractCost double satExecuteCost sat++) { optionsReservationCosts[sat]* = optionsPurchasedSatPer[sat]; = optionsExecutionCosts[sat]*optionsExecuted[i][sat sumSatContracts+=(satContractCost+satExecuteCost); } cumrptionsC+= sumSatContracts; } optionsContractCosts[i]=sumSatContracts; cumulativeOptionsCost[i]=cumOptionsC; } excessCost= new double[demand.length]; double cumExcess=O; for i=0; (int i<excessSatLevels.length;i++){ excessCost[i]=0; for(int j=0; j<excessSatLevels[i].length; j++) { excessCost[i]+=satellites[j].getPriceDouble(excessSatLevels[i][j], I cumExcess+excessCost[i]; cumulativeCostWith0ptions [i]=cumExcess+cumulativeOptionsCost [i] } optionsAndExcessCost = new double [2] [demand. length] optionsAndExcessCost [0] =optionsContractCosts optionsAndExcessCost[l]=excessCost; } public void outputOptionsResults() System.out.println('----------Options ContractCosts ------- ") System . out .println(Arrays . toString (optionsContractCosts)); System.out.println(----------OptionsuReservationaCosts-------System . out . println (Arrays . toString (optionsReservationCosts)); System.out.println("----------OptionsExecutionCosts-------") System . out . printin (Arrays . toString (optionsExecutionCosts)) 74 duration); onand, Execution"); System.out.println("UpperBoundonleservati for(int i =0; i <optionsUpperBounds.length; i++) { System.out.println("Satellite,,"+i+"ReservationUB:,;"+optionsUpperBounds[i][0]); System.out.println(Satellite "+i+",ExecutUion UB:+optionsUpperBounds[i[1]); } System.out.println(" for(int i=0; ---- --- i<demand.length; OptionsExecuted---------") i++ { ) System. out .println(Arrays toString (optionsExecuted [iI)); } System.out.println(" -OptionsuCostsePer i=0; i++) for(int i<demand.length; Period ------- "); { System.out.println("Period:,,"+i); System.out.printin(optionsAndExcessCost [0][i]); } System.out.println( for(int i =0; i ExcessAmountaandCostsPerPeriod,,-----" < demand.length; i { ++) System.out.println("Period: "+i); System.out.println("ExcessIevel System. out. println :"+Arrays.toString(excessSatLevels[i])); ("Excess, cost: "+excessCost [iI); } } public void setDecisionStages() { decisionStage [0]=true; for(int node=1; node< nodes; node++) if(decisionPt[node]==true) decisionStage { { [(node/(stageNodes+1))+1]=true; node+=stageNodes; } } } public int getNumberStepso) return numberSteps; } public int getNodes() return { nodes; } public int getNumSatLevels() return { satLevels.length; } } A.2 Demand Generator import java.util.Arrays; import java.util.Random; import javax.swing.J0ptionPane; import org.apache.commons.math3.distribution.*; import org.apache.commons.math3.random.RandomGenerator; public class Demand { 75 private static double private static int public static MAXREGIONDEMAND = 20; CONTINGENCY-DURATION = 2; AbstractRealDistribution[] getContingencies(int[] distributionTypes, boolean defaultEnabled int nbrRegions = distributionTypes.length; double normal-mu; double normal-sigmaSq; AbstractRealDistribution[] contingencies = new for(int i=0; i<nbrRegions; i++) { if(distributionTypes[i]==1) if AbstractRealDistribution[nbrRegions]; { (defaultEnabled) { normal-mu = 5; normal-sigmaSq = 2; NormalDistribution n = new NormalDistribution(normal-mu, normal-sigmaSq); contingencies[i] = n; } else { String normal-mu- string = J0ptionPane.showInputDialog("Enteruaumuuvalueu forLthe)normaladistributionudescribinguregiona" normal-mu = Double.parseDouble(normal-mu-string); String normal-sigmaSq-string = JOptionPane.showInputDialog("Enterasigma -squaredovalueuforudistributionu"+i+":j"); normal-sigmaSq = Double.parseDouble(normal-sigmaSq-string); NormalDistribution n = new contingencies[i] n; = NormalDistribution(normalmu, normalsigmaSq); } } } return contingencies; } public static int AbstractRealDistribution[] nbrRegions double = getDistributions(int[] distributionTypes, boolean distributionTypes.length; normal-mu; double normal-sigmaSq; double beta-alpha; double beta-beta; double cauchy-x; double cauchy-y; double chisquared-k; double exponential-lambda; double fisherSnedecor-dl; double fisherSnedecor-d2; double gamma-k; double gamma-theta; RandomGenerator levy-randgen; double levymu; double levy-c; double lognormal-mu; double lognormal-sigmaSq; double uniform-lower; double uniform-higher; double weibull-lambda; double weibull-k; AbstractRealDistribution[] distributions 76 new AbstractRealDistribution[nbrRegions]; defaultEnabled Random ri = for(int i=0; new Randomo; i<nbrRegions; { i++) { if(distributionTypes[i]==1) { (defaultEnabled) if normal-mu 5; = normal-sigmaSq = 2; NormalDistribution distributions [i] n new = NormalDistribution(normal-mu, normal-sigmaSq); = n; } { else String forothe normal-mu-string normalLdistributionedescribingeregionu"+i+" normal-mu String -squaredevalue, = JfptionPane.showInputDialog("Enter amuevalue :"); forLadistributiont-"+i+" :,") Double.parseDouble(normal -mu-string); = normal-sigmaSq-string = JOptionPane.showInputDialog("EntermaLsigma ; normal-sigmaSq = Double.parseDouble(normal_sigmaSq-string) NormalDistribution n = distributions[i] = n; BetaDistribution n = distributions[i] = n; new NormalDistribution(normalmu, normal-sigmaSq); } } else if(distributionTypes[i]==2) if { (defaultEnabled) = 5; beta-alpha beta-beta 2; = new BetaDistribution(betaalpha, beta-beta); } else { String valueforothebeta beta-alpha.string JOptionPane.showInputDialog("Entercamalpba, distributionsdescribingregion,"+i+":,"); beta-alpha = String ,forotheebetaedistributionedescribi Double.parseDouble(beta-alpha-string); beta-betastring = JOptionPane.showInputDialog(Entereaubetavalue ngregionu"+i+":j"); beta-beta = Double.parseDouble(beta-beta-string); BetaDistribution n distributions[i] = n; = new BetaDistribution(betaalpha, betabeta); } } else if(distributionTypes if { i]==3) (defaultEnabled) { cauchy-x = 5; cauchy-y = 2; CauchyDistribution n = distributions n; [i] = new CauchyDistribution(cauchyx, cauchy-y); } else { String the cauchy-x-string = JOptionPane.showInputDialog("Enter aux valuefor cauchyadistributionudescribigjregionn"+i+:e"); cauchy-x String ,theecauchy = Double.parseDouble(cauchy-x-string); cauchy-y-string = JOptionPane.showInputDialog("Enter aeyvaluefor distributiondescribingaregion"+i+:"); cauchy-y = Double.parseDouble(cauchy-y-string); CauchyDistribution n distributions[i] = n; if(distributionTypes[i]==4) { } else if (defaultEnabled) { 77 = new CauchyDistribution(cauchy-x, cauchy-y); chisquaredk = 5; ChiSquaredDistribution n = new distributions[i] = ChiSquaredDistribution(chisquaredk) n; } else { String chisquared-k-string = JOptionPane.showInputDialog("Enteruaukvalue uforutheuchi-squaredudistributionudescribingaregionu"+i+":,"); chisquared-k = Double.parseDouble(chisquared-k-string); ChiSquaredDistribution n = new ChiSquaredDistribution(chisquared-k); distributions[i] = n; } } else if(distributionTypes[i]==5) { if (defaultEnabled) { exponential-lambda = 5; ExponentialDistribution = n new ExponentialDistribution( exponential-lambda); = n; distributions[i] } else { String exponential-lambda-string JOptionPane.showInputDialog("Enterua, = I ambda:value)forotheexponent:ialdistribut)iondescribing)region,"+i+":,"); = Double.parseDouble(exponential-lambda-string) exponential-lambda ExponentialDistribution n = new ExponentialDistribution( exponential-lambda); = distributions[i] n; } } else if(distributionTypesi]==6) { if (defaultEnabled) { fisherSnedecor-di 5; = fisherSnedecor-d2 = 2; new FDistribution n = FDistribution(fisherSnedecor-dl, fisherSnedecor-d2) n; distributions[i] } else { String fisherSnedecor-dlstring = JOptionPane.showInputDialog("Enteraudl ,valuefortheFisher-Snedecordistribution1describinguregion"+i+":,"); fisherSnedecor-di = Double.parseDouble(fisherSnedecor-dl-string); String fisherSnedecor.d2_string = J~ptionPane.showInputDialog("Enteruaudu valueuforotheFisher -Snedecoradistributionudescribinguregion,"+i+":,"); fisherSnedecor-d2 FDistribution = parseDouble(fisherSnedecor-d2_string) Double n = new FDistribution(fisherSnedecor-d1, distributions(i] fisherSnedecord2) =n; } } else if(distributionTypes[i==7) { if (defaultEnabled) { gamma-k = 5; gamma-theta = 2; GammaDistribution n = new distributions[i] = GammaDistribution(gammak, gammatheta); n; } else String gamma-k-string = J3ptionPane.showInputDialog("Enterakvalueforu theugammaudistributionAdescribinguregion,"+i+":'"); gamma-k = Double.parseDouble(gamma-k-string); String gamma-theta-string value fortheugammaudistributionadescribinguregion"+i+": 78 = ); JOptionPane.showInputDialog("Entereautheta gamma-theta = Double.parseDouble(gamma-theta-string); GammaDistribution n new = distributions[i] GammaDistribution(gamma-k, gamma-theta); n; } } { if(distributionTypes[i]==8) else if { (defaultEnabled) levy-randgen levy-mu (RandomGenerator) = new Random() 5; levy-c 5; LevyDistribution n = distributions = n; i] new LevyDistribution(levy-randgen, levy-mulevy-c); } { else String levy-mu-string ,theelevydistributiondescribinguregionu"+i+": levy-mu String theelevy JOptionPane.showInputDialog("Enteramu = valuefor "); distributionedescr ibing = Double.parseDouble(levy-mu-string); levy-c-string region, "+i+"; = levy-c J~ptionPane.showInputDialog("EnteruaLc = value foru "); Double.parseDouble(levy-c-string); levy-randgen (RandomGenerator) = LevyDistribution n = distributions[i] = n; new new Random() LevyDistribution(levy.randgen, levy-mulevyc); } else { if(distributionTypes[i]==9) if { (defaultEnabled) lognormal-mu = 5; = 2; lognormalsigmaSq LogNormalDistribution n new LogNormalDistribution(lognormal-mu, lognormal-sigmaSq); distributionsfi] n; = } else { String value forLtheolognormal lognormal mu-string distributionjdescribingaregion" lognormal-mu String = = JOptionPane .showlnputDialog ("Enter, amu, +i+":e"); Double.parseDouble(lognormal-mu-string) lognormal-sigmaSq-string = J3ptionPane.showInputDialog("Entersa, sigma-squareduvalue.forotheilognormaldistributionadescribingLregion,"+i+":,"); lognormal-sigmaSq Double.parseDouble(lognormal-sigmaSq-string); = LogNormalDistribution n = new n = LogNormalDistribution(lognormalmu, lognormal-sigmaSq); distributions [i] n; = } } else { if(distributionTypes[i]==10) if (defaultEnabled) { uniform-lower 5; uniform-higher 2; UniformRealDistribution new UniformRealDistribution(uniform_lower, uniformhigher); distributions[i] = n; } else String uniform-lower-string J~ptionPane.showInputDialog("Enterailower, = valueeforthe,,uniformdistributiondescribingregion,"+i+":'"); uniform-lower String highervalue = Double.parseDouble(uniform_lower-string); uniform-higher-string = JOptionPane.showInputDialog("Ente,,a fortheoparetadistributionadescribingeregion,"+i+" :"); uniform-higher = Double.parseDouble(uniformhigher-string); 79 UniformRealDistribution n = new UniformRealDistribution(uniformlower, uniformhigher); = n; distributions[i] } } else { if(distributionTypes[i]==11) if (defaultEnabled) { weibull-lambda weibullk = = 5; 2; n WeibullDistribution = weibull-k WeibullDistribution(weibull-lambda, new = n; distributions[i] } { else String weibull-lambdasstring J3ptionPane.showInputDialog("EnteruaL = lambdauvalueuforotheuweibulladistributionadescribingLregionu"+i+":,"); weibull-lambda String = Double.parseDouble(weibull_lambda_string); weibull-k.string = J~ptionPane.showInputDialog("Entereaukuvalue, forotheuweibulldistributiondescribingaregion"+i+":u"); weibullik = Double.parseDouble(weibull-k-string); n WeibullDistribution = distributions[i] = new weibullk WeibullDistribution(weibull-lambda n; } } else { System.out.println("DistributiontypenotLsupported."); } } return distributions; } public static double [[][] boolean[] periods, getDemand(int contingencies AbstractRealDistribution[] int , activeContingencies new = contDurationLeft double [][][] for (int i = new = simulatedDemand 0; double Random i < [][] ri runs; int new growth, double warProb) [] { boolean[distributions.length]; length]; double [runs] [periods] [distributions. { demandPeriods = [] [distributions.length]; = new i++) distributions, AbstractRealDistribution[] double false); Arrays.fill(activeContingencies, int[] runs, = new length]; double [periods] [distributions. Randomo; = new distributionsRun AbstractRealDistribution[] AbstractRealDistribution[distributions. length]; for(int period = double[] for 0; d (int new reg=O; if period++) period<periods; = { double [distributions.length]; reg++) reg<distributions.length; { (period==0) { double g double mu=distributions[reg].getNumericalMean); double var= = growth[reg]; distributions [reg].getNumericalVariance(; new distributionsRun[reg]= NormalDistribution(mu, } else if (period>0) { double g = double mu=distributionsRun[reg].getNumericalMean); double var= 80 growth[reg]; distributionsRun[reg].getNumericalVariance(; Math.sqrt(var)) distributionsRun[reg]= double while sample = distributions (sample < 0 sample = d[reg] new 11 NormalDistribution(mu*g, (reg] . sample sample > Math.sqrt(var () MAXREGIONDEMAND) { distributionsRun[reg].sampleo; sample; = if(activeContingencies(reg]== { true) contDurationLeft[reg]--; { if(contDurationLeft[reg]==0) activeContingencies[reg]=false; } double while contSample= (contSample contingencies[reg.sampleo; 0 < contSample = 11 contSample > (MAXREGIONDEMAND-sample)) contingencies[regl.sampleo; d[reg]+=contSample; } else { double warDraw = rl.nextDouble(; if(warDraw<warProb~reg]) double while sample)) { 1 { contSample= (contSample contingencies[regJ.sampleo; 0 < 11 contSample > (MAXREGIONDEMAND- t contSample = contingencies(reg].sampleo; d[reg]+=contSample; activeContingencies[reg]=true; contDurationLeft[reg]=CONTINGENCYDURATION; } } } demandPeriods[period]=d; } simulatedDemand[i]= demandPeriods; } return simulatedDemand; } A.3 public Satellite class Satellite { private String private int[] private int private double optionPrice; private double executionPrice; name; regions; capacity; 81 1re 1 I:IC2 nt. 12r h11 (t'tr private static double ] regPriceMult = gion new double[] {1, 1.1, 0.9, private double companyMult; private public satPriceMult; double (int[] Satellite = regions = capacity double int c, String n, r, companyM) { r; c; = n; name ] double = satPriceMultArr new double [r.length]; companyMult=companyM; satPriceMult=l*companyMult; for(int i =0; for i<satPriceMultArr.length; (int j=0; i++ ) { j<regPriceMult.length; if(regions[i]==j) j++) { { satPriceMult*=regPriceMult[j]; } } } public r) { [ void setRegions(int regions = r; I public { getRegions() int[] regions; return } public getName() String { name; return } public c) setCapacity(int void { capacity = c; I public int getCapacity() return { capacity; } getSatPriceMult() { public double satPriceMult; return } getPrice(int capUsed, int public double duration) double base; if { (duration < 12) base= (243.2 - 14.7*duration)*capUsed; I else if (duration > 12) base= (79.6 - { 0.2*duration)*capUsed; I else { base= 77*capUsed; 82 0.8, 1, 1, 1, 1.2, 1.3, 1.4, 1, 1}; return public base*satPriceMult; double getPriceDouble(double double if capUsed, int duration) { base; (duration { < 12) base= (243.2 14.7*duration)*capUsed; - } else if (duration > 12) base= (79.6 - base= 77*capUsed; 0.2*duration)*capUsed; } { else } return base*satPriceMult; } public static double int sum =0; for (int getPrice(int[] i=0; caps, i<caps.length; i++) int duration) { { sum+=caps [i] } if (duration < 12) return - (243.2 14.7*duration)*sum; } else if (duration > return else 12) (79.6 - { 0.2*duration)*sum; { return 77*sum; } public static double[] get0ptionsBase(double double lowerBoundRes; double upperBoundRes; double lowerBoundEx; double reservationPer, duration) { upperBoundEx; double [] int[] unitCap optionsBase = upperBoundRes= lowerBoundRes lowerBoundEx new new double [4]; {1}; Satellite.getPrice(unitCap, duration*2); 0; Satellite.getPrice(unitCap, double res double executionP = = int[] 0; = upperBoundEx = duration); reservationPer*upperBoundRes; = -(upperBoundEx/upperBoundRes)*res optionsBase [0=res; optionsBase[1]=executionP; optionsBase [2]=upperBoundRes; optionsBase [3]=upperBoundEx; return int optionsBase; 83 + upperBoundEx; Main() Method A.4 import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.Random; import org.apache.commons.math3.distribution.AbstractRealDistribution; public class MainMethod { public static void main(String[] args) { boolean isMultContractDurations=true; boolean isTimingRuns =false; int[] sir = new Satellite int(] s2r = new Satellite[] {0,1}; Satellite(s1r, int[] s2 = Satellite int int[] si = new new 40, "Apollo11", 1.1); {,2}; 40, "Apollo,13" , 1.0); Satellite(s2r, sats= new Satellite[] {s1,s2}; duration=12; int [] distTypes=new double[] growth double[] warProb int [] {l,,i}; new double []{i.01,1.012,1 new double []{.05,.01,.01 AbstractRealDistribution[] distributions AbstractRealDistribution[] contingencies o,"f r numRuns = / TI 11 int r int [ I11 s1, 1-ula i Demand.getDistributions(distTypes, true); Demand.getContingencies(distTypes, true); r 1; optAmt = new int[] doublet] try 11 n = optionsCumCosts {5, = 10, 15}; new double [optAmt.length]; { Connection con = null; ResultSet rs-lastSat = null; ResultSet rs-lastSim = null; ResultSet rs-lastTimeStep = null; 84 ResultSet = rs-durationID null; Class.forName("org. sqlite .JDBC"); con = java.sql.DriverManager getConnection("jdbc:sqlite:/Users/jlyd/rails-projects/ sat-planner/db/developmtentcsqlite3"); System.out . println("Connected Statement stit con.createStatement(); = insertSimulation String " INSERT INTO, Simulations(namne) "+ "VALUES(I'Fi rstSim ')"; stmt.executeUpdate(insertSimulation); rs-1astSim int =stmt .executeQuery(SELECT,,idFROM LlSimulation s ORDEREBY id DESCLIMIT 1") lastSim=-I; while (rs-lastSim.next)){ lastSim = rs-1astSim.getInt(id"); } { if(isMultContractDurations==true) double []][] numRuns , growth, simulatedDemand = Demand.getDemand(30, distributions, contingencies, capacity usimulationlD) warProb); System.out.println("Demandsucreated."); int[] satIDs =new int satIDCounter for(Satellite int[sats.length]; = s 0; { sats) stmt.executeUpdate("INSERTINTSaelltetes,(name , "VALUES,('NoName rs-lastSat =stmt . ',"+s.getCapacity()+" executeQuery (SELECT, ,"+lastSim+")'); idFROMSate 11 itesORDERBYad DESC ,LIM IT,); int lastSat=-l; { while(rslastSat.nexto) lastSat = rs-lastSat.getlnt("id"); satIDs[satIDCounter] for(int reg=0; = lastSat; reg< s.getRegions().length;reg++) { stmt.executeUpdate("INSERT,,INTOSatelliteRegions(satelliteID, regionID),I"+ "VALUES("+lastSat+",u"+(s.getRegionso[reg]+l)+") satIDCounter++; for(int run=0; int[] for(int run<simulatedDemand.length; timeStepIDs per=O; = new run++) { int[simulatedDemand[0].length]; per<simulatedDemand[0).length; per++) { stmt . executeUpdate("INSERT, JNTOutime-stepsu(run ,period, simulationID)u,"+ "VALUES ("+run+" ,"+per+", 85 "+lastSim+")"); =stmt.executeQuery("SELECT rs-lastTimeStep iduFROMutime-stepsu ORDERBYuidDESCuLIMITA"); int lastTimeStep=-i; { while(rs-lastTimeStep.nexto) lastTimeStep = rs-lastTimeStep.getInt("id"); } timeStepIDs[per]=lastTimeStep; } for(int d=3; d<duration+1; d*=2) { 18, d, c = new ContractScheduler(sats, ContractScheduler simulatedDemand[run], 6); Systemout.println("DurationAis:,"+d); c.csd(); c.outputDecisions(; rs-durationID = stat .executeQuery("SELECTidFROMu contract-durationSu"+ "WHEREmonths=e" +c.getDuration()); int durationID -1; = while(rs_durationID.next()){ durationID = rsdurationID.getInt("id"); } double cumCost=O; per++) per=O; per<c.getDemand).length; for(int { for(int r=O; r<c.getDemand()[per].length; stat .executeUpdate ( "INSERTu INT r++) { Demands ( timeStepID,regionID,-quantity ,uactual-bw ,LcontractDurationID)u"+ "VALUES("+timeStepIDs[per]+" ,j"+( r+1)+" ,"+c.getDemand() [per] [r]+" ,-1"+c.getActualBW() [c.getPath() [per]] [r]+" ,j"+durationID+")") } != (c.getPath()[per] if -1) { cumCost +=c.getNodeCost () [c .getPath for(int sat=O; [per]]; sat<c.getNodeSatBW)[0[].length; sat++){ stmt.executeUpdate("INSERTINTO. sat_levels,(timeStepID,asatelliteID,abandwidth,acost ,contractDurationID ,cumCost),"+ "VALUES("+timeStepIDs [per ,"+c.getNodeCost [sat]+" J+" ,,"+satIDs [sat)+",u"+c.getNodeSatBWo(c.getPatho(per]] () [c.getPath()[per]]+ ",u"+durationID+" ,"+ cumCost+")") } if( d== 3) { for(int optIndex=O; optIndex<optAmt.length; optIndex++) { int optionQuant 86 = optAmt[optIndex]; int[] optionsPurchased = new int[sats. length] for(int i =0; i<sats.length; { i++) optionsPurchased[i]=optionQuant; } c.getOptionsCost(optionsPurchased, .1, d) c.outputOptionsResults(); for(int sat=O; sat< sats.length; { sat++) stmt.executeUpdate("INSERT.INTO, options.costs,(timeStepID ecumOptC, ,optionsExecuted ,optionsPurchased excessCost ,cumTotalC,,contractDurationID ,ureservationPrice , executionPrice ,-optionsCost ,satelliteID),"+ "VALUES("+ timeStepIDs[per]+",e"+c.optionsExecuted[per][sat]+", "+optionQuant+",,"+c.optionsReservationCosts c.optionsExecutionCosts[sat]+",..."+c opt ionsContractCosts -"+ [sat]+" [per]+" ,e"+c .cumulative~ptionsCost [per]+ ",_"+c.excessCost [per]+","+c.cumulativeCostWithptions[per]+",+optionContractLookup(optionQuant)+",_"+satIDs [sat]+") } optionsCumCosts[optlndex]=c. cumulativeCostWith0ptions[c.getDemand().length-1]; stmt.executeUpdate (INSERT ,run, INTO, runcosts (cumCost ,simuIationID, contractDurationID),"+ "+lastSim+",_"+run+", "VALUES("+cumCost+", "+ durationID+") { if(d==3) for(int i=0; i<optionsCumCosts.length;i++) stmt.executeUpdate("INSERT { INTOrun costs,,( cumCost,osimulationlD,,run,,contractDurationID),"+ "VALUES("+optionsCumCosts[i]+",," +lastSim+",_"+run+", "+optionContractLookup(optAmt [i])+)"); int] for(int fixedLevelArray f=0; new = int[] 8, {5, f<fixedLevelArray.length; 111; { f++) int fixedLevel = fixedLevelArray(f]; int contractID = contractTableLookup(fixedLevel); int[] fixedSatLevels= double fixedCostPer i for(int =0; i = new int[sats.length]; 0; <sats.length; fixedSatLevels[i] fixedCostPer+= int nbrRegions = i++) sats[i].getPrice(fixedLevel, fixedDemandCovered = for i=0; i++) for i<nbrRegions; (int s=0; for new doublefnbrRegions]; { s<fixedSatLevels.length; (int r : { { s++) sats[s].getRegionso) if(r==i) 87 12); simulatedDemand [01[0].length; double[] (int { fixedLevel; = { fixedDemandCovered[i]+ fixedSatLevels[s] / (sats[s].getRegions().length+0.0); } modifiedDemand double []] = new double [simulatedDemand[0].length ][nbrRegions]; for(int i=0; i<modifiedDemand.length; i++) { for(int j=0; j<modifiedDemand[0].length; j++) { double diff = simulatedDemand[run][i][j] - fixedDemandCovered[j]; if(diff< 0.0000001) { modifiedDemand[i][j] = 0; modifiedDemand[i][j] = else { ContractScheduler modifiedDemand, 18, diff; cSpec = new ContractScheduler(sats, 3, 6); cSpec.csd(); cSpec.outputDecisionso(; double cumCost=0; for(int per=O; per<cSpec.getDemando.length; for(int r=0; per++) { r<cSpec.getDemando)[per].length; r++) { stmt.executeUpdate("INSERTeINT0,Demands( timeStepID,aregionID Lquantity ,actual-bw ,contractDurationID),"+ "VALUES("+timeStepIDs[per+",,"+( r+)+",,"+(simulatedDemand[run)[per] [r)+,,"+(cSpec.getActualBWO[cSpec.getPatho)[per]][r]+ fixedDemandCovered[r])+",,"+contractID+")"); d if t (cSpec.getPath()[per] -1) { cumCost+=(cSpec.getNodeCosto[cSpec.getPath()[per ]]+ fixedCostPer); for(int sat=0; sat<cSpec.getNodeSatBW()[0].length sat++)( stmt.executeUpdate("INSERTeINTO, sat levelsu(timeStepIDusatelliteID, bandwidth ,cost ,_contractDurationID ,cumCost),"+ "VALUES("+timeSteplDs[per ]+","+satIDs(sat]+",L"+(cSpec.getNodeSatBWO)[cSpec.getPatho)[per])[sat]+ getNodeCost 0)[cSpec.getPatho)[per]] fixedSatLevels[sat])+"LJ"+(cSpec. +fixedCostPer)+ ",,"+contract1D+",,"+ cumCost+")"); 88 stmt.executeUpdate ("INSERT (cumCost INT0run-costs ,simulationID, "+ ,run,contractDurationID) "VALUES("+cumCost+", "+astSim+","+run+", "+ contractID+")"); } } } if(isTimingRuns == true) { int maxRegions = 4; int maxSats=5; for(int timeRegions=3; for(int timeRegions<maxRegions; numSats=2; int[] numSats<maxSats; growthTiming double[] warProbTiming rangeMinG double rangeMaxG= 1.010; double rangeMinW double rangeMaxW = " r=0; double[timeRegions]; 1.00; = 0; = 0.05; r<distTypesTiming.length; Random rand double randomValueG = new r++) { Randomo; = rangeMinG + (rangeMaxG - rangeMinG) + (rangeMaxW - rangeMinW) rand.nextDouble(); growthTiming[r] double * double[timeRegions]; new = double for(int 1); new = { int[timeRegions]; distTypesTiming=new Arrays.fill(distTypesTiming, double[] { timeRegions++) numSats++) rand.nextDouble randomValueG; = randomValueW rangeMinW = (); warProbTiming[r] randomValueW; = } Satellite int [] satsT new Satellite [numSats]; = satCap=82; if(timeRegions==3) { if(numSats==2) int[] { siTreg Satellite Apollo,11", new int[] {0,1}; Satellite(slTreg, satCap, " satCap, " satCap, " satCap, " 1.1); int[] Apollou13", new = s1T = = s2Treg new Satellite s2T = satsT[0]= s1T; int[] {1,2}; new Satellite(s2Treg, 1.0); satsT[1]=s2T; else if(numSats==3) int[] Satellite Apollo,11", = new s1T = int[] {0,1}; new Satellite(slTreg, 1.1); int[] s2Treg Satellite Apollo,13", { slTreg = new = s2T int[] {1,2}; new Satellite(s2Treg, 1.0); int[] 89 s3Treg = new int [ {0}; FalconSat6", Satellite s3T satsT[01= slT; = new Satellite(s3Treg, satCap, 0.9); satsT[1] =s2T; satsT [2]=s3T; } else if(numSats==4) { int[] sITreg = new int [] Satellite Apollo1I", s2Treg = new int[] Satellite = s2T satCap, new {l,2}; Satellite (s2Treg, satCap, s3T = new Satellite(s3Treg, satCap, 1.0); int[] s3Treg = new int[] Satellite FalconSat6", {0,1}; new Satellite(siTreg, = 1.1); int[] Apollo,13", s1T {0}; 0.9); int [ s4Treg Satellite = new {2}; int[ s4T = new Satellite (s4Treg, satCap, ElonMusk", 1.11); satsT[0]= s1T; satsT [1] =s2T; satsT [2] =s3T; sats [3]=s4T; } } else if(timeRegions==4) int [] { siTreg = new int] Satellite = sIT new {0,1,3}; Satellite (slTreg, satCap, "Apollol11" satCap, "Apollo,13" satCap, "Apollol1l" satCap, Apollo.13" ,1.1); int ] s2Treg = new int[] 1,2}; { Satellite s2T = new Satellite (s2Treg, 1.0); satsT[O0]= s1T; satsT [1]=s2T; else if(timeRegions==5) int[] Satellite sITreg s1T { new = = new int[] Satellite {0,1,3}; (slTreg, 1.1); int[] s2Treg = new Satellite s2T = new int[] {1,2,4}; Satellite (s2Treg, 1.0); satsTO]= s1T; satsT 1]=s2T; AbstractRealDistribution[] getDistributions(distTypesTiming, true); 90 distributionsTiming = Demand. AbstractRealDistribution[] getContingencies(distTypesTiming, int runsPerRegSet for(int = Demand. run=O; =2; run<runsPerRegSet; int timingRuns int numPeriods=30; double [][][] distributionsTiming, contingenciesTiming true); contingenciesTiming, timingRuns, timingDemand growthTiming, for(int i=1; int run++) { 1; = = Demand.getDemand(numPeriods, warProbTiming); i<2; { i++) levels=1; { if(i==l) levels = 2; levels = 3; (i==3) { levels = } else { if(i==2) } else if 4; } else { if(i==4) levels=6; } else { if(i==5) levels=8; } levels=4; ContractScheduler satsT, 3, timingDemand[0], 24, cTime = new ContractScheduler( levels); cTime.csd(); stmt . executeUpdate simulat ionID , run ,numPeriods ,numSats , numSatLevels ,anumReg ,numNodes , "INSERTINTO,,t numSteps) im ing-runs( "+ VALUES("+lastSim+" ,"+run+", numPeriods+",,"+satsT.length+,-"+cTime.getNumSatLevels ()+",,"+timeRegions+,"+cTime.getNodes getNumberSteps()+")"); System.out.println("levelsudone: "+levels); } System.out.println("Runadone:,"+run); System.out.println("TimeRegNumu"+timeRegions+",done."); System.out.println("NumSatsdone:,"+numSats); } } } stmt.close(); con.close(); catch(SQLException ex) System.out.println("\n { -- SQIExceptionacaught--\n 91 "+ 0)+,"+cTime. !=null){ while(ex u"+ex.getMessage()); System.out.println("Message: System.out.println("SQLState:u,,"+ex.getSQLState ()); System. out. println("ErrorCode :u"+ex. getErrorCode 0) ex=ex.getNextException); System.out.println(""); } catch(Exception e) { e.printStackTrace 0; public static if int contractTableLookup(int (fixedL == return else if( fixedL) { { 5) 4; fixedL ==8 ) { return 5; else { return 6; } } public static int optionContractLookup(int optAmt) if(optAmt==5) { return if(optAmt==10) else 7; { return 8; returs 9; { 92 { Appendix B Web Application Code - Ruby on Rails B.1 View The view utilizes a proprietary package, Highcharts.js, to display simulation results. The package is free to use for non-commercial websites. For package details and download, see www.highcharts.com. <h2>Simulation Stats</h2> <table> <tr> <th>Number of Time <th>Number of <th>Number of Satellites</th> <th>Number of regions</th> <th>Test Steps</th> Runs</th> query</th> </tr> <tr> <td><%= TimeStep.stepsOnSim(CcurrentSim).count %></td> <td><%= TimeStep.stepsOnSim(OcurrentSim).select(:run).distinct.count <td><X= Qsats.count X></td> %></td> <td><%= OdemandLevels.select(:regionID).distinct.count <td><%= X/></td> TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(0,17,51,1) %></td> </tr> </table> <hl>Sat <X= Levels</hl> form-tag <%= select-tag nil, method: :simulation, :get do %> optionsfrom collectionforselect(Simulation.all, 93 ;id, :id, CcurrentSim.try(:id)) "Chooseasimulation", <%= submit-tag <% end <% if name: nil %> %> TimeStep.stepsOnSim('currentSim).select(:run).distinct.count <script $(function() type="text/javascript" =1 %> charset="utf-8"> { new Highcharts.Chart({ chart: { renderTo: title: "satLevels_12_chart" { text: "SatLevelsu12-mouContracts" }, xAxis: { type: "dateTime", title: { text: "TimeuPeriodO(3mo)" } }, yAxis: { title: { text : "Level,(Gbps)" }, series: <% Csats.each do Isat I %> { isatd%> name :"sat<= data: atTimeStepSat (ts , sat .id , 3) tof <%= (TimeStep.stepsOnSim(OcurrentSim)).map %> }.inspect }, <V. end V.> }); </script> $(function() -8"> charset="utf type="text/javascript" <script { new Highcharts.Chart({ chart: { renderTo: "satLevels_6-chart" }, title: text: "SatLevels,6-moContracts" type: "dateTime", }, xAxis: { title: { text: "TimePeriod,(3mo)" yAxis: title: { text: "Levelu(Gbps)" 94 { IteSatLevel. series: Osats.each <% do %> IsatI name : "sat, <%=,sat . id,%>" , <%= data: atTimeStepSat(ts, sat.id, 2).to_f <% }.inspect (TimeStep.stepsOnSim( currentSim)).map { Its SatLevel. Y> end %> </script> <script $(function() type="text/javascript" charset="utf -8"> { new Highcharts.Chart({ chart : { renderTo: "satLevels 3 chart" { title: text: "SatLevels 3-moeContracts" }, xAxis: { type: title: "dateTime", { text: "TimePeriod(3mo)" text: "Level }, yAxis: { title: { (Gbps)" }, series: <% Csats.each do %> IsatI { name: data: atTimeStepSat(ts sat.id, 1).to.f <% end "sat, <%= }.inspect <%=sat.id,%> (TimeStep.stepsOnSim (OcurrentSim)).map %> %> I }); </script> <script $(function() type="text/javascript" charset="utf-8"> { new Highcharts.Chart({ chart: { renderTo: "cumulativecost-chart" }, title: { text : "CumulatIve-Cst of }, xAxis: { 95 Run" { Its SatLevel. type: "dateTime", title: { text: "TimePeriod,(3mo)" yAxis: title: { text: "Cost,($)" series: { name:"Cumulative ts, CostJforul2-moucontracts", { Itsl SatLevel.cumCost( map { Itsl SatLevel.cumCost( { Itst SatLevel.cumCost( { Itsl SatLevel.cumCost( data: <%= (TimeStep.stepsOnSim(CcurrentSim)).map { Itsi SatLevel.cumCost( data: <%= (TimeStep.stepsOnSim(DcurrentSim)).map 3, Osats.first).to-f }.inspect *1> 1, name:"CumulativeuCostofor,6-mocontracts", data: ts, 2, Osats.first).to_f }.inspect <%= (TimeStep.stepsOnSim(CcurrentSim)) %> { name:"CumulativeCostofor,3-moucontracts", data: ts, 1, Osats.first).to.f <%= (TimeStep.stepsOnSim(OcurrentSim)).map }.inspect %> }, { name:"CumulativeUCostoforoFixedl+3-moucontracts", data: ts, 4, Osats }.inspect first).to-f <%= (TimeStep.stepsOnSim(CcurrentSim)).map %> }, { name:"CumulativeuCostuforuFixed2+3-mo ts, 5, Osats first).to-f contracts", %> }.inspect name:"CumulativeCostoforFixed3+3-moucontracts", data: ts, 6, Osats.first).to-f }.inspect <%= (TimeStep.stepsOnSim(OcurrentSim)).map { Itsi SatLevel.cumCost( %> { name:"CumulativeCostoforuOptionsl+3mouContracts", data: cumCost(ts, 7, Osats first) <%= (TimeStep.stepsOnSim(DcurrentSim)).map to_f }.inspect { Itsl OptionsCost. %> }, { name:"CumulativeUCostoforuOptions2+3mouContracts", data: <%= cumCost(ts, 8, Osats.first).to_f }.inspect (TimeStep.stepsOnSim(OcurrentSim)).map { Itsl OptionsCost. Itsl OptionsCost. %> { name:"CumulativeuCostofru~ptions3+3mouContracts", data: cusCost (ts , 9, Csats first).tno.f <4= }.inspect (TimeStep.stepsOnSim(CcurrentSim)).map { V.> 96 }); </script> <script type=" text /javascript" charset="utf -8"> { $(function() new Highcharts.Chart({ chart: { renderTo: "cumulativecost-optionschairt" { title: text: "CumulativeCosteofRun" type: "dateTime", }, { xAxis: title: { text: "TimePeriod(3mo)" text: "Cost,($)" } { yAxis: title: { } series: { name:"CumulativeuCostforu3-moucontracts, data: ts, 1, Qsats.first).tof }.inspect <%= (TimeStep.stepsOnSim(OcurrentSim)).map { ltsI SatLevel.cumCost( { Itsl OptionsCost. { tsl OptionsCost. { ts %> name:"CumulativeCostforOptionsl+3moContracts, data: cumCost(ts, 7, Osats.first).to~f <%= }.inspect (TimeStep.stepsOnSim(OcurrentSim)).iap %> }, name:"Cumulative data: cumCost(ts, 8, <%= Options2+3moContracts, %> }.inspect Qsats.first).to-f Costufor (TimeStep.stepsOnSim(OcurrentSim)).map name:CumulativeCostforOptions3+3moContracts", data: cumCost(ts, 9, Osats.first).tof <%= }.inspect (TimeStep.stepsOnSim(OcurrentSim)).map %> }, }) ; </script> <script $(function() type="text/javascript" charset="utf { new Highcharts.Chart({ chart: { 97 -8"> l OptionsCost. "bw-demand-chart" renderTo: title: i text: "BandwidthuanduDemanduforuRegionul" 1, xAxis: { type: title: "dateTime", { text: "TimeuPeriodO(3mo)" yAxis: title: { text: "Level,(Gbps)" } series: name:"Bandwidthofor,12-moucontracts", data: atTimeStepRegConActual(ts, 1, 3).to-f <%= (TimeStep.stepsOnSim(QcurrentSim)).map }.inspect { Itsl Demand. { Itsl Demand. { Itsl Demand. { ItsI Demand. Itsl Demand. Itsi Demand. { Itsi Demand. %> { name:"Bandwidthoforu6-moucontracts", data: atTimeStepRegConActual(ts, <%= (TimeStep.stepsOnSim(CcurrentSim)).map 1, 2).to-f }.inspect %> { name:"Bandwidthoforu3-moucontracts", data: atTimeStepRegConActual(ts, 1, 1).tof <%= (TimeStep.stepsOnSim(OcurrentSim)) map }.inspect Y> { name:"Demand", data: atTimeStepRegConQuantity(ts, 1 1).tof <%= (TimeStep.stepsOnSim(currentSim)).map }.inspect 7.> 1, { name:"BandwidthoforFixedl+3-moucontracts", data: atTimeStepRegConActual(ts, 1, 4).tof <%= (TimeStep.stepsOnSim(CcurrentSim)) }.inspect map { %> { name:"BandwidthoforFixed2+3-moucontracts", data: atTimeStepRegConActual(ts, <%= (TimeStep.stepsOnSim(CcurrentSim)).map 1, 5).to-f }.inspect { V> { name:"BandwidthoforFixed3+3-moucontracts", data: <%= (TimeStep.stepsOnSim(CcurrentSim)).map atTimeStepRegConActual(ts, 1, 6).to-f }.inspect %> 1); </script> <div id= "satLevels-12_chart" style= "width:600px;,height:350px;"></div> 98 <div id= "satLevels_6-chart style= "width:600px;,hoight :350px;"></div> <div id= "satLevels3-chart style= "width:600px;,height <div id= "cumulativecost-chart" style= <div id= "cumulativecost-options-chart" <div "bw-demand-chart" <% else id= style= style= 350px;"></div> "width:600px;,height:450px;"></div> "width:800px;,height %> <script type=" text/javascript" charset="utf -8"> { $(function() new Highcharts.Chart({ { chart: renderTo:'cost-histogram', defaultSeriesType:'column', borderWidth:0, backgroundColor:'#eee', borderWidth:1, borderColor: #ccc', plotBackgroundColor:'#fff', plotBorderWidth:1, plotBorderColor:'#ccc' credits:{enabled:false}, exporting:{enabled:false}, title:{text: Cost Histogram}, legend:{ //enabled:false tooltip:{ borderWidth:1, formatter:function() return { '<b>Range:</b><br/> '<b>Count:</b> '+ '+ this.x +'<br/>)+ this.y; } plotOptions:{ column:{ shadow:false, borderWidth:.5, borderColor:'#666', pointPadding:0, groupPadding:0, color: spline 'rgba(204,204,204,.85)' :{ shadow:false, marker:{ radius:1 } areaspline :{ color:'rgb(69, 114, fillColor:'rgba(69, :700px;"></div> "width:600px;,height :350px;"></div> 167)', 114, 167,.25)', shadow:false, marker:{ radius:1 99 xAxis :{ 0 < 20','>= ['>= categories: 40','>= 20 140', '>= 140 < 160', '>= 160 < 180', '>= 280','>= 280 300 < 320', 300','>= < 40 < 180 320 '>= < 60','>= 200', '>= 340', < 200 60 < 80','>= < 220', '>= 340 '>= < 360', < 80 220 '>= < 360 100','>= < < 100 240', '>= 380', 120', '>= 240 < '>= 380 < 120 260', '>= 260 < 400'], < labels :{ rotation:-90, y:20, style: { fontSize:'8px', fontWeight:'normal', color:'#333' lineWidth:0, lineColor:'#999', tickLength:70, tickColor:'#cccl, { yAxis: title: { text: "Frequency" } series: { name :"3moContractCosts", data: [<%= RunCost.onSim(CcurrentSim).countBetween(0,20000, RunCost.onSim(8currentSim) .countBetween(20000,40000, 1) 1) %>,<= %>,<V= RunCost.onSim(OcurrentSim) .countBetween 1) %>,< %= RunCost .onSim(8currentSim).countBetween(60000,80000, 1) %>,<V= RunCost.onSim( OcurrentSim).countBetween(80000,100000, 1) %>, <%= RunCost.onSim(6currentSim).countBetween(100000,120000, %>,<%= RunCost.onSim(currentSim).countBetween(120000,140000, 1) %>, <%= RunCost.onSim(OcurrentSim). (40000,60000, countBetween(140000,160000, 1) %>,<%= RunCost .onSim(OcurrentSim) .countBetween(160000,180000, RunCost .onSim(OcurrentSim) .countBetween(180000,200000, (200000,220000, 1) %>, <%= RunCost.onSim( OcurrentSim) .countBetween(240000,260000, 1) %>, 1) %>, <%= %>, RunCost .onSim(OcurrentSim) <%= RunCost.onSim(OcurrentSim).countBetween(280000,300000, countBetween(300000,320000, RunCost .onSim(OcurrentSim) (360000,380000, 1) %>, 1) %>, <%= 1) %>, <%= 1) 1) %>, <%= RunCost.onSim( .countBetween(260000,280000, .>, <%= RunCost.onSim(#currentSim). RunCost.onSim(QcurrentSim).countBetween(320000,340000, .countBetween(340000,360000, %>, <%= RunCost.onSim(OcurrentSim) .countBetween currentSim).countBetween(220000,240000, 1) 1) 1) 1) %>, <%= <%= RunCost.onSim(OcurrentSim) .countBetween <%= RunCost.onSim(OcurrentSim).countBetween(380000,400000, 1) %> { name:"6mouContractCosts", data: [<%= RunCost.onSim( RunCost.onSim(OcurrentSim) .countBetween(20000,40000, (40000,60000, 2) V.>,<V= 2) currentSim).countBetween(0,20000, 2) %>,<%= %>,<V= RunCost.onSim( OcurrentSim) .countBetween RunCost .onSim(OcurrentSim).countBetween(60000,80000, 2) %>,<V= RunCost .onSim( OcurrentSim) .countBetween(80000,100000, 2) %>, <.= RunCost.onSim(OcurrentSim) .countBetween(100000,120000 %>,< %= RunCost.onSim(OcurrentSim).countBetween(120000,140000, 2) %>, <%= RunCost.onSim(OcurrentSim). countBetween(140000,160000, 2) %>,<%= RunCost.onSim(OcurrentSim).countBetween(160000,180000, 2) %>, < = RunCost .onSim( (200000,220000, currentSim) .countBetween(180000,200000, 2) %>, <%= %>, <%= RunCost .onSim(OcurrentSim) countBetween(300000,320000, 2) %>, 2) %>, <%= .countBetween(280000,300000, 2) %>, 2) %>, 2) %>, <%= RunCost.onSim( .countBetween(260000,280000, <%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(CcurrentSim).countBetween(320000,340000, 2) %>, 2) %>, <%= <%= RunCost.onSim(CcurrentSim).countBetween <%= RunCost.onSim(CcurrentSim).countBetween(380000,400000, 2) %> { name:" 12moContract,,Costs", data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, RunCost.onSim(CcurrentSim).countBetween(20000,40000, 3) 100 2) <V= RunCost.onSim(OcurrentSim) .countBetween RunCost .onSim(CcurrentSim) RunCost.onSim(OcurrentSim).countBetween(340000,360000, (360000,380000, %>, RunCost.onSim(OcurrentSim).countBetween(220000,240000, OcurrentSim) .countBetween(240000,260000, 2) 2) , 3) %>,<%= %>,<%= RunCost.onSim(CcurrentSim).countBetween (40000,60000, 3) %>,<%= RunCost.onSim(OcurrentSim).countBetween(60000,80000, OcurrentSim).countBetween(80000,100000, %>,<%= RunCost.onSim(CcurrentSim).countBetween(120000,140000, countBetween(140000,160000, 3) %>,<%= 3) %>, <%= %>, 3) 3) %>, 3) %>, 3) %>, %>, <%= %>, 3) <%= 3) %>, <%= RunCost.onSim( <%= RunCost .onSim(OcurrentSim) .countBetween(260000,280000, 3) %>, <%= RunCost.onSim(CcurrentSim). <%= RunCost .onSim(CcurrentSim) .countBetween(320000,340000 RunCost.onSim(CcurrentSim).countBetween(340000,360000, 3) 3) <%= RunCost.onSim (CcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween <%= RunCost.onSim(OcurrentSim).countBetween(280000,300000, countBetween(300000,320000, (360000,380000, %>, RunCost.onSim(OcurrentSim).countBetween(220000,240000, CcurrentSim) .countBetween(240000,260000, 3) RunCost.onSim( RunCost.onSim(CcurrentSim).countBetween(160000,180000, RunCost.onSim(CcurrentSim).countBetween(180000,200000, (200000,220000, %>,<%= 3) <%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, 3) %>, 3) %>, , 3) <%= %>, <%= RunCost.onSimOcurrentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(380000,400000, 3) %> }, { name: "Fixedl,+,3,MoCosts", [<%= data: RunCost.onSim(OcurrentSim).countBetween(0,20000, RunCost.onSim(CcurrentSim).countBetween(20000,40000, (40000,60000, %>,<%= 4) 4) RunCost.onSim(OcurrentSim).countBetween(60000,80000, OcurrentSim).countBetween(80000,100000, 4) %>, RunCost .onSim(OcurrentSim) (200000,220000, 4) %>, <%= 4) 4) %>, <%= 4) 4) %>, <%= 4) %>, <%= 4) %>, <%= <%= 4) %>, 4) %>, <V= RunCost.onSim(OcurrentSim) .countBetween 4) <V= 4) RunCost.onSim (currentSim). %>, 4) <V= RunCost.onSim( %>, .countBetween(260000,280000, <%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween(320000,340000, RunCost.onSim(OcurrentSim).countBetween(340000,360000, %>, %>, RunCost .onSim(OcurrentSim) RunCost.onSim(OcurrentSim).countBetween(280000,300000, 4) %>,<%= RunCost.onSim( RunCost.onSim(OcurrentSim).countBetween(220000,240000, countBetween(300000,320000, (360000,380000, 4) %>,<%= RunCost.onSim(OcurrentSim).countBetween(160000,180000, .countBetween(180000,200000, OcurrentSim) .countBetween(240000,260000, %>,<V= <%= RunCost.onSim(OcurrentSim).countBetween(100000,120000, %>,<V= RunCost.onSim (currentSim).countBetween(120000,140000, countBetween(140000,160000, 4) %>,<V= RunCost.onSim(CcurrentSim).countBetween 4) <%= %>, RunCost.onSim (currentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(380000,400000, 4) %> { name: Fixed2,+,3,MoCost s" data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, RunCost.onSim(OcurrentSim).countBetween(20000,40000, (40000,60000, 5) 5) '.>,<V= V>,<V.= RunCost.onSim(OcurrentSim).countBetween(60000,80000, OcurrentSim).countBetween(80000,100000, 5) %>, <V= 5) %>,<%= OcurrentSim) 5) %>, 5) %>, <V= 5) 5) V>, <%= 5) %>, 5) %>, <%= RunCost.onSim( <V= 5) V.>, <%= 5) 5) %>, <%= RunCost.onSim(OcurrentSim).countBetween 5) %>, 5) <%= RunCost.onSim( %>, .countBetween(260000,280000, <%= RunCost.onSim(OcurrentSim). OcurrentSim).countBetween(320000,340000, RunCost.onSim(OcurrentSim).countBetween(340000,360000, %>, RunCost.onSim( <%= RunCost.onSim ( currentSim). <%= RunCost .onSim(QcurrentSim) <V= RunCost.onSim(OcurrentSim).countBetween(280000,300000, countBetween(300000,320000, 5) %>, RunCost.onSim(OcurrentSim).countBetween(220000,240000, .countBetween(240000,260000, (360000,380000, %>,<%= 5) RunCost.onSim(OcurrentSim).countBetween(160000,180000, RunCost.onSim(currentSim).countBetween(180000,200000, (200000,220000, %>,<%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, %>,<= RunCost.onSim(OcurrentSim).countBetween(120000,140000, countBetween(140000,160000, 5) RunCost.onSim(CcurrentSim).countBetween 5) %>, <%= RunCost.onSim(CcurrentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(380000,400000, 5) %> ] }, { name: Fixed3,+ 3uMouCosts data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, RunCost.onSim(OcurrentSim).countBetween(20000,40000, (40000,60000, 6) 6) V>,<%= V>,<V.= RunCost.onSim(CcurrentSim).countBetween 6) %>,<%= RunCost.onSim(OcurrentSim).countBetween(60000,80000, 6) %>,<V= RunCost.onSim( OcurrentSim).countBetween(80000,100000, 6) %>, <%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, %>,<%= RunCost.onSim(OcurrentSim).countBetween(120000,140000, 6) %>, <%= RunCost.onSimn(CcurrentSim). countBetween(140000,160000, RunCost.onSim( (200000,220000, 6) %>,<%= RunCost.onSim(CcurrentSim).countBetween(160000,180000, currentSim).countBetween(180000,200000, 6) %>, </= %>, %>, 6) %>, RunCost.onSim( (360000,380000, 6) %>, %>, <%= 6) %>, <%= <%= RunCost.onSim( 6) %>, <%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween(320000,340000, currentSim).countBetween(340000,360000, 6) %>, <%= RunCost .onSim(CcurrentSim) .countBetween(260000,280000, <V= RunCost.onSim(OcurrentSim).countBetween(280000,300000, countBetween(300000,320000, 6) <%= RunCost.onSim( OcurrentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(220000,240000, OcurrentSim) .countBetween(240000,260000, 6) 6) 6) %>, <%= RunCost.onSim(OcurrentSim).countBetween(380000,400000, { 101 6) %>, <%= RunCost.onSim(OcurrentSim).countBetween 6) %> ] 6) name:"Optionslu+u3uMouCosts", data: [<%= RunCost.onSim(CcurrentSim).countBetween(0,20000, RunCost .onSim(OcurrentSim) .countBetween(20000,40000, (40000,60000, OcurrentSim) 7) %>,<Y= 7) %>,<%= RunCost.onSim(OcurrentSim).countBetween(60000,80000, .countBetween(80000,100000, %>, 7) %>,<%= 7) 7) (200000,220000, %>, %>, 7) <%= 7) 7) %>, <%= 7) <%= %>, %>, 7) <%= 7) <%= RunCost.onSim(OcurrentSim). 7) %>, <%= RunCost.onSim(CcurrentSim).countBetween 7) %>, <%= RunCost.onSim( %>, 7) <%= RunCost.onSim(CcurrentSim). 7) <%= RunCost.onSim(OcurrentSim).countBetween(320000,340000, RunCost.onSim(currentSim).countBetween(340000,360000, %>, %>,<%= RunCost.onSim( RunCost.onSim(CcurrentSim).countBetween(260000,280000, RunCost.onSim(CcurrentSim).countBetween(280000,300000, 7) %>, <%= RunCost.onSim(OcurrentSim).countBetween(220000,240000, countBetween(300000,320000, (360000,380000, 7) RunCost.onSim(CcurrentSim).countBetween(160000,180000, RunCost.onSim(QcurrentSim).countBetween(180000,200000, OcurrentSim).countBetween(240000,260000, %>,<%= <%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, 7>,<7= RunCost.onSim(OcurrentSim).countBetween(120000,140000, countBetween(140000,160000, 7) RunCost.onSim(OcurrentSim).countBetween 7) %>, <%= %>, <%= RunCost.onSim(CcurrentSim).countBetween RunCost.onSim(currentSim).countBetween(380000,400000, 7) %> { name:"Options2,+u3AMouCosts', data: (40000,60000, 8) 8) 7>,<%= 8) 8) %>, <%= %>, 8) <%= 8) %>, 8) <%= %>, 8) %>, %>, <%= 8) %>, <%= 8) %>, <%= RunCost.onSim( RunCost.onSim(OcurrentSim).countBetween(260000,280000, 8) %>, <%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween(320000,340000, 8) RunCost.onSim(CcurrentSim).countBetween(340000,360000, 8) 8) <%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(CcurrentSim).countBetween RunCost .onSim(OcurrentSim) .countBetween(280000,300000, countBetween(300000,320000, (360000,380000, %>, RunCost.onSim(OcurrentSim).countBetween(220000,240000, OcurrentSim).countBetween(240000,260000, 8) %>,<%= RunCost.onSim( %>,<%= RunCost.onSim(CcurrentSim).countBetween(160000,180000, RunCost.onSim(OcurrentSim) .countBetween(180000,200000, (200000,220000, 8) <%= RunCost.onSim(OcurrentSim).countBetween(100000,120000, %>, RunCost.onSim(6currentSim).countBetween(120000,140000, countBetween(140000,160000, %>,<%= %>,<%= RunCost.onSim(CcurrentSim).countBetween %>,<%= RunCost .onSim(OcurrentSim) .countBetween(60000,80000, 8) OcurrentSim).countBetween(80000,100000, 8) [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, RunCost.onSim(CcurrentSim).countBetween(20000,40000, %>, 8) <%= %>, <%= RunCost.onSim(OcurrentSim).countBetween RunCost.onSim (currentSim).countBetween(380000,400000, 8) %> { name:"Options3u+u3uMoCosts", data: [<*/= RunCost.onSim(CcurrentSim).countBetween(0,20000, RunCost.onSim(OcurrentSim).countBetween(20000,40000, (40000,60000, 9) 7.>,<%= 9) %>,<%= RunCost.onSim(OcurrentSim).countBetween(60000,80000, 9) OcurrentSim) .countBetween(80000,100000, 9) %>,<%= (200000,220000, 9) %>, %>, 9) 9) 9) %>, 9) %>, 9) %>, RunCost.onSim( <%= 9) <%= RunCost.onSim(CcurrentSim). 9) %>, <%= 9) %>, <%= RunCost.onSim( <%= RunCost.onSim(OcurrentSim).countBetween(260000,280000, .>, <%= RunCost.onSim(CcurrentSim). 9) RunCost.onSim(ScurrentSim).countBetween(320000,340000, RunCost .onSim(CcurrentSim) .countBetween(340000,360000, %>, %>,<%= <%= RunCost.onSim(CcurrentSim).countBetween <%= RunCost.onSim(OcurrentSim).countBetween(280000,300000, 9) %>, <%= RunCost.onSim(CcurrentSim).countBetween(220000,240000, countBetween(300000,320000, (360000,380000, 9) RunCost.onSim(CcurrentSim).countBetween(160000,180000, RunCost.onSim(CcurrentSim).countBetween(180000,200000, OcurrentSim).countBetween(240000,260000, %>,<%= <%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, %>, %>,<%= RunCost.onSim(CcurrentSim).countBetween(120000,140000, countBetween(140000,160000, 9) RunCost.onSim(CcurrentSim).countBetween 9) %>, 9) %>, <.= <%= RunCost.onSim(CcurrentSim).countBetween <%= RunCost.onSim(8currentSim).countBetween(380000,400000, 9) %> { name:'3mo Curve', type: spline , visible:false, data: [<%= RunCost.onSim(currentSim).countBetween(0,20000, countBetween(20000,40000, 1) onSim(CcurrentSim).countBetween(60000,80000, 1) %>, 1) %>,<%= 1) %>, 1) %>, <%= 1) 1) 1) %>, %>,<%= RunCost. %>,<%= RunCost.onSim(OcurrentSim). 1) %>, 1) %>,<%= <%= RunCost.onSim(CcurrentSim).countBetween <%= RunCost.onSim(OcurrentSim).countBetween(200000,220000, OcurrentSim).countBetween(220000,240000, %>, RunCost.onSim(OcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween(140000,160000, RunCost.onSim(OcurrentSim).countBetween(160000,180000, (180000,200000, V>,<V= RunCost.onSim(CcurrentSim).countBetween(80000,100000, <%= RunCost.onSim(OcurrentSim).countBetween(100000,120000, countBetween(120000,140000, 1) 1) %>,<%= RunCost.onSim(OcurrentSim) .countBetween(40000,60000, 1) %>, <%= RunCost.onSim( <%= RunCost .onSim(OcurrentSim).countBetween(240000,260000, RunCost.onSim(CcurrentSim).countBetween(260000,280000, 102 1) %>, <%= RunCost.onSim(OcurrentSim). countBetween(280000,300000, 1) %>, <%= RunCost.onSim(CcurrentSim).countBetween(300000,320000, 1) %>, <V= RunCost.onSim(CcurrentSim).countBetween(320000 340000, 1) .>, <%= RunCost.onSim(CcurrentSim).countBetween (340000,360000, 1) .>, <%= RunCost.onSim(OcurrentSim).countBetween(360000,380000, 1) %>, <%= RunCost.onSim( CcurrentSim) .countBetween(380000,400000, //color: V> ] 1) 'rgba(204,204,255,.85)' }, { name:'6mo Curve', type:'spline , visible:false, data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, countBetween(20000,40000, 2) %>, countBetween(120000,140000, 2) 2) <%= RunCost.onSim(CcurrentSim).countBetween(140000,160000, %>, RunCost.onSim(CcurrentSim).countBetween(160000,180000, (180000,200000, 2) <%= %>, %>, 2) countBetween(280000,300000, 2) %>,<%= %>, <%= RunCost .onSim(currentSim) .countBetween(240000,260000, %>, 2) <%= %>, %>, 2) %>, <%= RunCost.onSim(OcurrentSim). RunCost.onSim(OcurrentSim).countBetween(300000,320000, RunCost.onSim(CcurrentSim).countBetween(320000,340000, 2) %>, 2) 2) <%= %>, <%= RunCost.onSim(CcurrentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(360000,380000, <%= OcurrentSim) .countBetween (380000 ,400000, //color: 2) RunCost.onSim(CcurrentSim).countBetween(260000,280000, (340000,360000, 2) <%= RunCost.onSim(CcurrentSim).countBetween <%= RunCost.onSim(OcurrentSim).countBetween(200000,220000, 2) %>, <%= RunCost.onSim( CcurrentSim) .countBetween(220000,240000, 2) V>,<V= RunCost.onSim(OcurrentSim). 2) %>,<%= RunCost. %>,<%= RunCost .onSim(CcurrentSim) .countBetween(80000,100000, <%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, 2) %>,<%= RunCost.onSim(OcurrentSim). onSim(CcurrentSim).countBetween(60000,80000, 2) 2) %>,<%= RunCost.onSim(CcurrentSim).countBetween(40000,60000, 2) %>, <%= RunCost.onSim( %> 'rgba(204,204,255,.85)' { name:'12mo Curve', type:'spline , visible:false, data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, countBetween(20000,40000, 3) onSim(OcurrentSim).countBetween(60000,80000, 3) %>, 3) %>,<V= RunCost.onSim(OcurrentSim). 3) %>,<= RunCost. %>,<V= RunCost.onSim(OcurrentSim).countBetween(80000,100000, <%= RunCost.onSim(CcurrentSim).countBetween(100000 countBetween(120000,140000, 3) %>,<%= RunCost.onSim(OcurrentSim).countBetween(40000,60000, 3) 120000, 3) %>,<%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween(140000,160000, %>, RunCost.onSim(OcurrentSim).countBetween(160000,180000, 3) %>, 3) %>,<= <%= RunCost.onSim(OcurrentSim).countBetween (180000,200000, 3) %>, <%= RunCost.onSim(currentSim).countBetween(200000,220000, 3) %>, <%= RunCost.onSim( OcurrentSim).countBetween(220000,240000, 3) Y.>, <%= RunCost.onSim(OcurrentSim).countBetween(240000,260000, 3) %>, <%= RunCost.onSim(OcurrentSim).countBetween(260000,280000, countBetween(280000,300000, 3) %>, <%= RunCost.onSim(CcurrentSim).countBetween(320000,340000, (340000,360000, 3) %>, <%= %>, <%= RunCost.onSim(OcurrentSim). 3) %>, <%= 3) 3) <%= %>, RunCost.onSim(OcurrentSim).countBetween RunCost .onSim(OcurrentSim).countBetween(360000,380000, OcurrentSim).countBetween(380000,400000, //color: 3) RunCost.onSim(OcurrentSim).countBetween(300000,320000, 3) %>, <%= RunCost .onSim( %> ] 'rgba(204,204,255,.85)' { name:'Fixedl+3mo Curve', type:'splinel, visible:false, data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, 4) %>, <%= RunCost.onSim(OcurrentSim). %>,<%= RunCost.onSim(OcurrentSim).countBetween(40000,60000, 4) %>,<%= RunCost. onSim (OcurrentSim) .countBetween (60000 80000, 4) %>, <%= RunCost .onSim (OcurrentSim) .countBetween (80000 ,100000, countBetween(20000,40000, 4) %>, 4) <%= RunCost.onSim(OcurrentSim).countBetween(100000,120000, countBetween(120000,140000, 4) %>, <.= RunCost .onSim(OcurrentSim) .countBetween(160000,180000, (180000,200000, 4) %>, <%= %>, %>,<V= RunCost.onSim(OcurrentSim). 4) %>, <V= RunCost.onSim(CcurrentSim) RunCost.onSim(OcurrentSim).countBetween(200000,220000, OcurrentSim).countBetween(220000,240000, 4) 4) RunCost.onSim(OcurrentSim).countBetween(140000,160000, 4) %>, <%= 4) %>,<= .countBetween RunCost.onSim( <%= RunCost.onSim(OcurrentSim).countBetween(240000,260000, <%= RunCost.onSim(OcurrentSim).countBetween(260000,280000, 4) %>, <%= RunCost.onSim(OcurrentSim). countBetween(280000,300000, 4) %>, <%= 4) %>, RunCost.onSim(OcurrentSim).countBetween(300000,320000, RunCost.onSim(OcurrentSim).countBetween(320000,340000, (340000,360000, 4) %>, <V= 4) %>, <%= RunCost.onSim(OcurrentSim).countBetween(360000,380000, OcurrentSim) .countBetween(380000 400000, 4) %> ] 103 4) %>, <%= RunCost.onSim(OcurrentSim).countBetween 4) %>, <%= RunCost.onSim( //color: 'rgba(204,204,255,.85)' }, { name:'Fixed2+3mo Curve', , type:'spline visible:false, data: [<%= RunCost.onSim(CcurrentSim) .countBetween(0,20000, 5) %>,<%= RunCost .onSim(OcurrentSim) countBetween(20000,40000, 5) %>, 5) <%= RunCost.onSim(O currentSim).countBetween(100000,120000, 5) countBetween(120000,140000, %>, 5) OcurrentSim) %>, %>,<%= RunCost.onSim(OcurrentSim). %>,<%= 5) <%= RunCost.onSim(OcurrentSim) .countBetween .countBetween(220000,240000, 5) <%= RunCost.onSim(OcurrentSim).countBetween(260000,280000, %>, RunCost %>,<%= 5) 7>, <%= RunCost.onSim( .>, <%= RunCost.onSim(OcurrentSim).countBetween(200000,220000, 5) 7>, <%= RunCost.onSim(DcurrentSim) .countBetween(240000,260000, 5) (180000,200000, 5) .countBetween(80000,100000, RunCost.onSim(OcurrentSim).countBetween(140000,160000, <%= RunCost.onSim(6currentSim). countBetween(160000,180000, 5) .countBetween(40000,60000, %>,<%= RunCost.onSim(CcurrentSim) 5) onSim(CcurrentSim). countBetween(60000,80000, %>,<%= RunCost.onSim(OcurrentSim) 5) 5) countBetween(280000,300000, %>, <%= 5) .>, <%= 5) <%= RunCost.onSim(OcurrentSim) .countBetween %>, <%= RunCost.onSim(OcurrentSim).countBetween(360000,380000, OcurrentSim).countBetween(380000,400000, //color: %>, 5) RunCost .onSim(OcurrentSim).countBetween(320000,340000, (340000,360000, %>, <%= RunCost.onSim(OcurrentSim). RunCost.onSim(OcurrentSim).countBetween(300000,320000, 5) %>, <%= RunCost.onSim( 5) %> 1 'rgba(204,204,255,.85)' { name:'Fixed3+3mo Curve', type:'spline , visible:false, data: [<%= RunCost.onSim(OcurrentSim).countBetween(0,20000, 6) onSim(OcurrentSim) .countBetween(60000,80000, 6) 6) 6) <%= %>, %>, 6) 6) 6) RunCost.onSim(OcurrentSim).countBetween(320000,340000, 6) (340000,360000, %>, 6) //color: %>, 6) 7>, <%= RunCost.onSim( <%= RunCost.onSim(OcurrentSim). %>, 6) %>, <%= <%= RunCost.onSim(OcurrentSim).countBetween <%= RunCost.onSim(OcurrentSim).countBetween(360000,380000, OcurrentSim).countBetween(380000,400000, 6) %>,<%= <%= RunCost.onSim(OcurrentSim) .countBetween(240000,260000, <%= RunCost.onSim(tcurrentSim).countBetween(300000,320000, %>, 6) <%= RunCost.onSim(CcurrentSim).countBetween RunCost.onSim(CcurrentSim).countBetween(260000,280000, countBetween(280000,300000, %>,<%= RunCost. %>,<%= RunCost.onSim(OcurrentSim). 7>, <%= RunCost.onSim(OcurrentSim).countBetween(200000,220000, 6) CcurrentSim) .countBetween(220000,240000, %>, 6) <%= RunCost.onSim(CcurrentSim).countBetween(140000,160000, %>, RunCost.onSim(6currentSim).countBetween(160000,180000, (180000,200000, 6) %>,<%= RunCost.onSim(CcurrentSim) .countBetween(80000,100000, .>, <%= RunCost.onSim(CcurrentSim).countBetween(100000,120000, countBetween(120000,140000, 6) %>,<%= RunCost.onSim(OcurrentSim). 6) %>,<%= RunCost.onSim(OcurrentSim) .countBetween(40000,60000, 6) countBetween(20000,40000, 6) %>, <%= RunCost.onSim( %> 1 'rgba(204,204,255,.85)' { name:"Optionslu+u3uMouCosts", type:'spline , visible:false, data: [<%= (40000,60000, 7) %>,<%= %>,<%= RunCost.onSim( 7) 7>, 7) 7) %>,<%= 7) 7>, <%= 7>, <%= 7) 7) 7>, 7) 7>, </= 7) %>, 7) %>, 7) 7>, <%= 7) %>, <%= RunCost.onSim( RunCost.onSim(CcurrentSim).countBetween(260000,280000, 7) 7>, <%= RunCost.onSim(CcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween(320000,340000, RunCost.onSim(DcurrentSim).countBetween(340000,360000, 7) %>, <%= { name:"Options2u+u3uMouCosts", 104 7) 7>, <%= RunCost.onSim(OcurrentSim).countBetween <%= RunCost.onSim(OcurrentSim).countBetween(380000,400000, type: spline ', 7) <%= RunCost.onSim(OcurrentSim). <%= RunCost.onSim(OcurrentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(280000,300000, countBetween(300000,320000, (360000,380000, 7>, RunCost.onSim(OcurrentSim).countBetween(220000,240000, OcurrentSim).countBetween(240000,260000, 7) %>,<%= RunCost.onSim( RunCost.onSim(OcurrentSim).countBetween(160000,180000, RunCost.onSim(OcurrentSim).countBetween(180000,200000, (200000,220000, 7) <%= RunCost.onSim(OcurrentSim).countBetween(100000,120000, currentSim).countBetween(120000,140000, countBetween(140000,160000, %>,<Y= %>,<%= RunCost.onSim(OcurrentSim).countBetween RunCost.onSim(icurrentSim).countBetween(60000,80000, OcurrentSim).countBetween(80000,100000, 7) RunCost.onSim(OcurrentSim).countBetween(0,20000, RunCost.onSim(OcurrentSim).countBetween(20000,40000, 7) 7> 1 visible:false, [<%= data: RunCost.onSim(CcurrentSim).countBetween(0,20000, RunCost.onSim(OcurrentSim).countBetween(20000,40000, (40000,60000, %>, <%= 8) 8) %>, <%= RunCost.onSim(OcurrentSim).countBetween(120000,140000, countBetween(140000,160000, 8) %>,<V= (200000,220000, 8) V>, </= %>, <%= 8) 8) %>, <%= 8) %>, <%= 8) %>, <%= <%= %>,<%= RunCost.onSim( <%= 8) %>, 8) <%= %>, RunCost.onSim(OcurrentSim).countBetween 8) <%= 8) RunCost.onSim(CcurrentSim). %>, <%= 8) %>, <%= RunCost.onSim( .countBetween(260000,280000, RunCost.onSim(OcurrentSim). RunCost.onSim(OcurrentSim).countBetween(320000,340000, RunCost.onSim(OcurrentSim).countBetween(340000,360000, %>, 7.>, RunCost .onSim(CcurrentSim) RunCost.onSim(OcurrentSim).countBetween(280000,300000, 8) %>,<V= RunCost.onSim(CcurrentSim).countBetween(220000,240000, countBetween(300000,320000, (360000,380000, 8) RunCost.onSim(OcurrentSim).countBetween(160000,180000, OcurrentSim) .countBetween(240000,260000, 8) RunCost.onSim(CcurrentSim).countBetween RunCost.onSim(CcurrentSim).countBetween(100000,120000, RunCost.onSim(OcurrentSim).countBetween(180000,200000, 8) %>,<V= RunCost.onSim(OcurrentSim).countBetween(60000,80000, OcurrentSim).countBetween(80000,100000, %>,<%= 8) 8) <%= %>, RunCost.onSim(OcurrentSim).countBetween RunCost.onSim(CcurrentSim).countBetween(380000,400000, 8) %> { name:"Options3,+,3,MoCosts, type:'spline , visible:false, [<%= data: RunCost .onSim(8currentSim) (40000,60000, OcurrentSim) %>,<V= 9) %>,<%= RunCost.onSim(ocurrentSim).countBetween(0,20000, .countBetween(20000,40000, 9) 9) %>, <%= RunCost .onSim (0currentSim). RunCost.onSim(CcurrentSim).countBetween(120000,140000, countBetween(140000,160000, (200000,220000, OcurrentSim) %>, <%= 9) %>, 9) %>,<%= <%= 9) %>, <%= 9) %>, <%= 9) %>, 9) <%= %>, <%= -8"> { new Highcharts.Chart({ chart : { renderTo: 'satLevel-histogram defaultSeriesType:lcolumn', borderWidth:0, backgroundColor:'#eee', borderWidth:1, borderColor:'#cccl, plotBackgroundColor:'#fff', plotBorderWidth:1, plotBorderColor:'#ccc' credits:{enabled:false}, exporting:{enabled:false), title:{text:'SatLevel 9) %>, Histogram }, legend:{ //enabled:false 105 9) RunCost.onSim(OcurrentSim). 9) %>, <%= RunCost.onSim(CcurrentSim).countBetween 9) %>, <%= 9) %>, <%= RunCost.onSim( .countBetween(260000,280000, RunCost.onSim(CcurrentSim). 9) %>, <%= <%= RunCost.onSim(OcurrentSim).countBetween RunCost.onSim(OcurrentSim).countBetween(380000,400000, charset="utf %>,<%= RunCost.onSim( RunCost.onSim(OcurrentSim).countBetween(320000,340000, </script> type="text/javascript" <%= RunCost .onSim(OcurrentSim) RunCost.onSim(currentSim).countBetween(280000,300000, (360000,380000, %>, %>,<V= countBetween (100000 ,120000, RunCost.onSim(OcurrentSim).countBetween(220000,240000, RunCost.onSim(QcurrentSim).countBetween(340000,360000, $(function() 9) 9) 9) .countBetween RunCost.onSim(CcurrentSim).countBetween(160000,180000, .countBetween(240000,260000, countBetween(300000,320000, <script RunCost .onSim(CcurrentSim) RunCost.onSim(OcurrentSim).countBetween(60000,80000, countBetween (80000,100000, RunCost.onSim(OcurrentSim).countBetween(180000,200000, 9) %>,<%= 9) %> I tooltip :{ borderWidth:1, formatter:function() { return '<b>Range:</b><br/> '<b>Count:</b> '+ this.x +'<br/>'+ '+ this.y; } plotOptions:{ column:{ shadow:false, borderWidth:.5, borderColor:'#666', pointPadding:0, groupPadding:0, 'rgba(204,204,204,.85)' color: spline:{ shadow:false, marker:{ radius:1 } }, areaspline:{ color:'rgb(69, 114, 167)', fillColor:'rgba(69, 114, 167,.25)', shadow:false, marker:{ radius:1 } }, xAxis:{ 16 < 16','>= '>= 18','>= < 34', 32 0 ['>= categories: '>= < 2','>= 2= 18 < 20','>= 34 < 36', '>= 4 < 4','>= 20 < 36 6','>= 6 < 8','>= 8 < 10','>= 22','>= 22 < < 38', '>= 38 24','>= 24 10 < 26','>= 26 < < 12','>= 28','>= 28 12 < 14','>= < 30','>= 30 14 < < 32', < 40'], labels:{ rotation:-90, y:20, style: { fontSize:'8pxl, fontWeight:'normal', color:'#333' }, lineWidth:0, lineColor:'#999', tickLength:70, tickColor:'#ccc', }, yAxis: { title: { text: "Frequency" }, series: <% Qsats.each do ]sat[ %> { %>, <%= name:" sat,,<%=,sat data: [<%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(0,2,sat.id,1) ,id,%>,_12,mo", TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(2,4,sat.id,1) 106 %>, <%= TimeStep.stepsOnSim( OcurrentSim).countAtSatLevel(4,6,sat.id,1) id,1) %>, %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(6,8,sat. <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(8,10,sat.id,1) %>,<%= TimeStep.stepsOnSim( OcurrentSim).countAtSatLevel(10,12,sat.id,1) %>, <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(12,14, sat.id,1) %>, <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(14,16,sat.id,1) %>, <7= TimeStep. stepsOnSim(CcurrentSim).countAtSatLevel(16,18,sat.id,1) countAtSatLevel(18,20,sat.id,1) 7>, %>, <%= TimeStep.stepsOnSim(CcurrentSim). TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(20,22,sat.id,1) <%= <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(22,24,sat.id,1) QcurrentSimm).countAtSatLevel(24,26,sat.id,1) %>, %>, %>, <%= TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(26,28, %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(28,30,sat.id,1) .>, <%= TimeStep. stepsOnSiim(CcurrentSim).countAtSatLevel(30,32,sat.id,1) %>, <%= TimeStep.stepsOnSim(QcurrentSim). sat.id,1) countAtSatLevel(32,34,sat.id,1) '/>, <%= TimeStep.stepsOnSim (currentSim).countAtSatLevel(34,36,sat.id,1) <%= TimeStep.stepsOnSim(DcurrentSim).countAtSatLevel(36,38,sat.id,1) QcurrentSim).countAtSatLevel(38,40,sat.id,1) %>, %>, <%= TimeStep.stepsOnSim( %>] }, { %>, name sat' <7=sat . idi/>U6umo" data: [<%= TimeStep.stepsOnSim( currentSim).countAtSatLevel(0,2,sat.id,2) <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(2,4,sat.id,2) OcurrentSim).countAtSatLevel(4,6,sat.id,2) %>, id,2) %>, <%= TimeStep.stepslnSim(OcurrentSim).countAtSatLevel(8,10,sat.id,2) %>, QcurrentSim).countAtSatLevel(10,12,sat.id,2) sat.id,2) %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(14,16,sat.id,2) countAtSatLevel(18,20,sat.id,2) %>, TimeStep. stepsOnSim (currentSim).countAtSatLevel(30,32,sat.id,2) <%= %>, 7,>, <%= TimeStep.stepsOnSim( %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(26,28, stepsOnSim (CcurrentSim) . countAtSatLevel countAtSatLevel(32,34,sat.id,2) <%= TimeStep. %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(20,22,sat.id,2) QcurrentSim).countAtSatLevel(24,26,sat.id,2) <%= %>, <%= TimeStep.stepsOnSim(OcurrentSim). <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(22,24,sat.id,2) %>, %>,<7= TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(12,14, stepsOnSim(OcurrentSim).countAtSatLevel(16,18,sat.id,2) sat. id ,2) <%= TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(6,8,sat. %>, (28 ,30,sat . id ,2) %>, <%= TimeStep. %>, <%= TimeStep.stepsOnSim(OcurrentSim). %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(34,36,sat.id,2) TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(36,38,sat.id,2) QcurrentSim).countAtSatLevel(38,40,sat.id,2) %>, 7>, <%= TimeStep.stepsOnSim( 7>] { id,7,>3,mo", name: sat data: [<Y.= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(0,2,sat.id,3) <%=,sat . 7>, <%= TimeStep.stepsOnSim(currentSim).countAtSatLevel(2,4,sat.id,3) QcurrentSim).countAtSatLevel(4,6,sat.id,3) %>, <%= TimeStep.stepsOnSim( %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(6,8,sat. id,3) %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(8,10,sat.id,3) %>,<7= TimeStep.stepsOnSim( OcurrentSim).countAtSatLevel(10,12,sat.id,3) %>,<%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(12,14, sat.id,3) %>, <%= TimeStep.stepsOnSim (currentSim).countAtSatLevel(14,16,sat.id,3) %>, <%= TimeStep. stepsOnSim(CcurrentSim).countAtSatLevel(16,18,sat.id,1) countAtSatLevel(18,20,sat.id,3) %>, <%= TimeStep.stepsOnSim(OcurrentSim). %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(20,22,sat.id,3) <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(22,24,sat.id,3) OcurrentSim).countAtSatLevel(24,26,sat.id,3) sat.id,3) %>, <%= TimeStep.stepsOnSim( 7,>, <%= TimeStep.stepsOnSim( %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(26,28, currentSimi).countAtSatLevel(28,30,sat.id,3) 7>, <%= TimeStep. %>, <%= TimeStep.stepsOnSim( OcurrentSim). stepsOnSim(OcurrentSim).countAtSatLevel(30,32,sat.id,3) countAtSatLevel(32,34,sat.id,3) %>, TimeStep.stepsOnSirm(OcurrentSim).countAtSatLevel(34,36,sat.id,3) %>, <%= <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(36,38,sat.id,3) OcurrentSim).countAtSatLevel(38,40,sat.id,3) 7,>, 7>, <%= TimeStep.stepsOnSim( %>] { name:'sat <%= sat.id type:'spline 7> 12 mo Curve', , visible:false, data: [<%= TimeStep.stepsOnSim( QcurrentSim).countAtSatLevel(0,2,sat.id,1) TimeStep.stepsOnSimC(currentSim).countAtSatLevel(2,4,sat.id,1) %>, <%= countAtSatLevel(4,6,sat.id,1) TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(6,8,sat.id,1) TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(8,10,sat.id,1) countAtSatLevel(10,12,sat.id,1) <%= TimeStep.stepsOnSim( %>, %>,<%= %>, %>, <%= TimeStep.stepsOnSim( OcurrentSim). '/>, <7= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(12,14,sat.id,1) currentSim).countAtSatLevel(14,16,sat.id,1) QcurrentSim).countAtSatLevel(16,18,sat.id,1) <%= %>, <%= TimeStep.stepsOnSim (currentSim). 7,>, 7>, <%= TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(18,20, 107 sat.id,1) %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(20,22,sat.id,1) stepsOnSim(CcurrentSim).countAtSatLevel(22,24,sat.id,1) %>, countAtSatLevel(24,26,sat.id,1) %>, <%= <%= TimeStep. <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(26,28,sat.idl) <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(28,30,sat.id,1) OcurrentSim).countAtSatLevel(30,32,sat.id,1) sat.id,1) %>, %>, TimeStep.stepsOnSim(OcurrentSim). %>, %>, <%= TimeStep.stepsOnSim( %>, <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(32,34, <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(34,36,sat.id,1) stepsanSim(OcurrentSim).countAtSatLevel(36,38,sat.id,1) %>, <%= %>, <%= TimeStep. TimeStep.stepsOnSim(OcurrentSim). countAtSatLevel(38,40,sat.id,1) %>] { name:"satu<%/=usat.idu />uemoCurve", type: 'spline', visible:false, [<%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(0,2,sat.id,2) data: %>, <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(2,4,sat.id,2) CcurrentSim).countAtSatLevel(4,6,sat.id,2) id,2) %>, %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(8,10,sat.id,2) %>, CcurrentSim).countAtSatLevel(10,12,sat.id,2) sat.id,2) %>, <%= <%= TimeStep. <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(20,22,sat.id,2) %>, <%= %>, <%= TimeStep.steps stepsOnSim(OcurrentSim).countAtSatLevel(30,32,sat.id,2) %>, %>, OnSim( TimeStep.stepsOnSim (OcurrentSim).countAtSatLevel (26 ,28, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(28,30,sat.id,2) countAtSatLevel(32,34,sat.id,2) %>, <%= TimeStep.stepsOnSim(OcurrentSim). TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(22,24,sat.id,2) OcurrentSim).countAtSatLevel(24,26,sat.id,2) %>, <%= %>,<%= TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(C currentSim).countAtSatLevel(14,16,sat.id,2) countAtSatLevel(18,20,sat.id,2) sat.id,2) %>, TimeStep.stepsOnSim( TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(12,14, stepsanSim(CcurrentSim).countAtSatLevel(16,18,sat.id ,2) %>, <%= <%= %>, <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(6,8,sat. %>, %>, <%= TimeStep. <%= TimeStep.stepsOnSim(CcurrentSim). <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(34,36,sat.id,2) TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(36,38,sat.id,2) V>, <%= TimeStep.stepsOnSim( %>, OcurrentSim).countAtSatLevel(38,40,sat.id,2) %>] { name :"satu type: visible: data: %>, <%=Lsat .id,,%>,3,moCurve" 'spline', false, [<%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(0,2,sat.id,3) <%= TimeStep.stepsOnSims(OcurrentSim).countAtSatLevel(2,4,sat.id,3) OcurrentSim).countAtSatLevel(4,6,sat.id %>, <%= TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(6,8,sat. ,3) %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(8,10,sat.id,3) %>,<V.= TimeStep.stepsOnSim( OcurrentSim).countAtSatLevel(10,12,sat.id,3) %>, <%= TimeStep.stepsOnSims(OcurrentSim).countAtSatLevel(12,14, sat.id,3) %>, <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(14,16,sat.id ,3) %>, <%= TimeStep. id,3) %>, stepsOnSim(OcurrentSim).countAtSatLevel(16,18,sat.id,1) countAtSatLevel(18,20,sat.id,3) <%= %>, %>, <V= TimeStep.stepsOnSim(OcurrentSim). <%= TimeStep.stepsOnSim(6currentSim).countAtSatLevel(20,22,sat.id,3) TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(22,24,sat.id,3) OcurrentSim).countAtSatLevel(24,26,sat.id,3) sat.id,3) %>, %>, <%= countAtSatLevel(32,34,sat.id,3) %>, <Y.= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(26,28, %>, <%= TimeStep. <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(34,36,sat.id,3) OcurrentSim).countAtSatLevel(38,40,sat.id ,3) V>] }, end %> </script> id="cost-histogram" %>, <%= TimeStep.stepsOnSim(CcurrentSim). <%= TimeStep.stepsOnSim(CcurrentSim).countAtSatLevel(36,38,sat.id,3) <% V.>, TimeStep.stepsOnSim( <%= TimeStep.stepsOnSim(OcurrentSim).countAtSatLevel(28,30,sat.id,3) stepsOnSim(CcurrentSim).countAtSatLevel(30,32,sat.id,3) <div %>, style="height:o500px"></div> 108 %>, <V= TimeStep.stepsOnSim( %>, <div style="height: 500px"></div> id="satLevel-histogram" <% end %> <h2>TimingRuns</h2> <table> <tr> <td>number regions</td> <td>number nodes</td> <td>number steps</td> <% for row in OtimingRuns %> <tr> <td><%= row.numReg %></td> row.numNodes %></td> <td><%= row.numSteps %></td> <td><%= </tr> <% end %> <h2>Utilization</h2> <table> <tr> <td>12 <td>6 <td>3 mo Average Utilization</td> mo Average Utilization</td> mo Average Utilization</td> <td>Fixedl + 3mo Avg Util</td> <td>Fixed2 + 3mo Avg Util</td> <td>Fixed3 + 3mo Avg Util</td> </tr> <tr> <td><%m CdemandLevels.where ("contractDurationID=,?",3).sum(:quantity) 17", / OdemandLevels.where("contractDurationlD, 3).sum(:actual-bw) %></td> <td><%= CdemandLevels.where("contractDurationID,= 2).sum(:actual-bw) %></td> ,?",2).sum(:quantity) / CdemandLevels.where(" contractDurationDu,=-?", <td><%= OdemandLevels.where("contractDurationID= 1).sum(:actual-bw) contractDurationlD,=,?", <td><%.= OdemandLevels.where("contractDurationIDu= contractDurationID,=,?", <td><%= 4).sum(:actual-bw) <td><%= 5).sum(:actual_bw) / OdemandLevels.where(" ?",4).sum(:quantity) / OdemandLevels.where(" a?",5).sum(:quantity) / OdemandLevels.where(" ,?",6).sum(:quantity) / OdemandLevels.where(" %></td> OdemandLevels.where("contractDurationID,= contractDurationID,=,?", ,?",1).sum(:quantity) %></td> %></td> OdemandLevels.where("contractDurationlD-= contractDurationIDl=?", 6).sum(:actual-bw) %></td> </tr> </table> <h2> Relative Utilization Comparisons </h2> <table> <tr> <td> </td> <td>12 mo Average Utilization</td> <td>6 mo Average Utilization</td> <td>3 mo Average Utilization</td> <td>Fixedl + <td>Fixed2 + 3mo Avg Util</td> <td>Fixed3 + 3mo Avg Util</td> 3mo Avg Util</td> 109 <tr> <td>12 mo <td><%= Average U</td> (OdemandLevels.where("contractDurationID,=u?",3).sum(:quantity) ,=,?", 3).sum(:actual-bw)) / .where ("contractDurationIDu=,?", <td><%= 3).sum(:actual-bw) (OdemandLevels.where ,=,?", / (OdemandLevels.where ,=,?", / (OdemandLevels.where ,=u?", / <td><%= 3) .sum(:actual bw)) / / / 3) .sum(:actualbw)) ,1).sum(:quantity) / OdemandLevels OdemandLevels.where("contractDurationID / ,4).sum(:quantity) / OdemandLeveIs OdemandLevels.where("contractDurationID ,5).sum(:quantity) / OdemandLevels 5).sum(:actualbw))%></td> / OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationIDu=,?" .where("contractDurationIDu=u?", ademandLevels 4).sum(:actualbw))%></td> (OdemandLevels.where("contractDurationID,=,?",3).sum(:quantity) u=,?", / OdemandLevelsw.here("contractDurationID (OdemandLevels.where("contractDurationIDu=u?" .where("contractDurationID,=2?", ,2).sum(:quantity) 1).sum(:actualbw))%></td> (OdemandLevels.where("contractDurationIDU=,?",3).sum(:quantity) u=,?", <td><%= / (OdemandLevels.where("contractDurationIDu=,?" .where("contractDurationIDu=,?", OdemandLevels 2).sum(:actualbw))X></td> ("contractDurationIDu=u?",3).sum(:quantity) 3) .sum(:actualbw)) / OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationID=L?" .where("contractDurationIDu=u?", <td><7.= / ("contractDurationIDU=u?",3).sum(:quantity) 3) .sum(:actualbw)) ,3).sum(:quantity) (CdemandLevels.where("contractDurationIDu=,?" .where("contractDurationIDu=,?", <td><7.= OdemandLevels.where("contractDurationID )%></td> ("contractDurationID,=,?",3).sum(:quantity) 3).sum(:actual _bw)) / (OdemandLeveIs.where ("contractDurationID,=,?" ,6).sum(:quantity) / OdemandLeveIs 6).sum(:actual-bw))%></td> </tr> <tr> <td>6 mo Average U</td> <td></td> <td><%= (CdemandLevels.where("contractDurationID,=,?",2).sum(:quantity) =u?" , 2) .sum(:actualbw)) / .where("contractDurationID,=u?", <td><%= / 2).sum(:actualbw)) (OdemandLevels.where u=,?", / <td><%= 2).sum(:actual _bw)) / / OdemandLevels OdemandLevels.where("contractDurationID ,1).sum(:quantity) / OdemandLevels ,2).sum(:quantity) / OdemandLevels.where("contractDurationID ,4).sum(:quantity) / OdemandLevels 4).sum(:actualbw) )%></td> (OdemandLevels.where("cantractDurationIDu=u?" ,=,?", / (OdemandLevels.where("contractDuration1Du=?" .where("contractDurationIDu=u?", ,2).sum(:quantity) 1).sum(:actualbw) )%></td> ("contractDurationID,=,?" 2) .sum(:actualbw)) ,2).sum(:quantity) (OdemandLevels.where("contractDurationID=u?" .where("contractDurationIDu=,?", <td><%= OdemandLevels.where("contractDurationID 2).sum(:actualbw) )%></td> (OdemandLevels.where("contractDurationIDu=u?" u=j?", / (OdemandLevels.where("contractDurationID=,?" ,2).sum(:quantity) / MdemandLevels.where("contractDurationID (OdemandLevelI.where("contractDurationIDJ=U?" ,5).sum(:quantity) / OdemandLevels .where("contractDurationIDu=u?", 5).sum(:actual-bw) )%></td> <td><%= (OdemandLevels.where("contractDurationID=,?" ,=,?", 2) .sum(:actual bw)) / ,2).sum(:quantity) / OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationIDu?" ,6).sum(:quantity) / OdemandLevels .where("contractDurationIDu=u?", 6).sum(:actual-bw) )%></td> </tr> <tr> <td>3 mo Average U</td> <td></td> <td></td> <td><%= (OdemandLevels.where("contractDurationID=u?" / 1).sum(:actual-bw)) u=u?", .where("contractDurationIDu=u?", <td><%= 1).sum(:actualbw)) / 1).sum(:actualbw)) / (OdemandLevels.where ,=u?", / 5).sum(:actual-bw) Average / / 6).sum(:actual-bw) )%></td> <tr> mo OdemandLevels ,4).sum(:quantity) / OdemandLeveIs OdemandLevels.where("contractDurationID ,5).sum(:quantity) / OdemandLevels )%></td> </tr> <td>Fixedl / CdemandLevels.where("contractDurationID OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationIDu=u?" .where("contractDurationIDu=,?", ,1).sum(:quantity) 4).sum(:actual-bw) )%></td> ("contractDurationID,=u?",1).sum(:quantity) 1) .sum(:actual.bw)) / (OdemandLeveIs.where("contractDurationIDu=,?" .where("contractDurationIDu=u?", <td><%= ,1).sum(:quantity) (OdemandLevels.where("contractDurationIDu=,?",1).sum(:quantity) ,=u?", CdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationIDu=u?" .where("contractDurationID,=,?", <td><%= / 1).sum(:actual_bw) )%></td> (OdemandLevels.where("contractDurationID,=,?" ,=,?", ,1).sum(:quantity) (OdemandLevels.where("contractDurationIDu=?" U</td> <td></td> <td></td> 110 ,6).sum(:quantity) / OdemandLevels <td></td> <td><%= (OdemandLevels.where("contractDurationID,=?" ,=,?", 4).sum(:actual / bw)) .where("contractDurationlD,,,?", <td><%= 4).sum(:actual-bw) (OdemandLevels.where("contractDurationID,=,,?" 4).sum(:actual -bw)) / .where("contractDurationID,= <td><%= ,4).sum(:quantity) / ,4).sum(:quantity) / 5).sum(:actual-bw) / ,,=,?",5).sum(:quantity) / 6) .sum(:actual-bw) / OdemandLevels )%></td> OdemandLevels.where("contractDurationlD (OdemandLevels.where("contractDurationID=?" .where("contractDurationIDu=j?", CdemandLevels OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationID ?", 4). sum(:actual-bw)) / )%></td> (OdemandLevels.where("contractDurationID,=,?",4).sum(:quantity) ,=,?", DdemandLevels.where("contractDurationlD (OdemandLevels.where("contractDurationID=,,?",4).sum(:quantity) ,6).sum(:quantity) / OdemandLevels )/></td> </tr> <tr> <td>Fixed2 mo Average U</td> <td></td> <td></td> <td></td> <td></td> <td><%= (OdemandLevels.where " ("contractDurationID 5).sum(:actual-bw)) ',?", / .where("contractDurationlD=U?", <td><%= =?",5).sum(:quantity) / 5).sum(:actual-bw) 5).sum(:actualbw)) / / 6).sum(:actual-bw) OdemandLevels CdemandLevels.where("contractDurationID ('OdemandLevels.where("contractDurationID=,? .where("contractDurationlD,-=?", / )%></td> (OdemandLevels.where("contractDurationID,,=,?" ,5).sum(:quantity) =L? ", OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationIDj=x?",5).sum(:quantity) " ,6).sum(:quantity) / OdemandLevels )%></td> </tr> <tr> <td>Fixed3 mo Average U</td> <td></td> <td></td> <td></td> <td></td> <td></td> <td><%= (OdemandLevels.where _=U?", ("contractDuration1D / 6).sum(:actualbw)) =,?",6).sum(:quantity) / OdemandLevels.where(" contractDurationID (OdemandLevels.where("contractDurationID,=,?"6).sum(:quantity) .where("contractDurationID,=?", 6).sum(:actual-bw) / OdemandLevels )%></td> </tr> </table> <h2>BW above Fixed, Total BW and % of Total</h2> <table> <tr> <td>Fixedl</td> <td>Fixed2</td> <td>Fixed3</td> </tr> <tr> <td><%= OdemandLevels .where("contractDurationID OdemandLevels.where("contractDurationID,=,?,ANDquantity <td><%= =>7 ,4) .sum(: quantity) OdemandLevels.where ("contractDurationID,=_?,ANDquantity,>,8",5).sum(:quantity) CdemandLevels.where("contractDurationID,=,?,ANDuquantity>.8" <td><%= AND quantity,>5" ,5).count*8) OdemandLevels.where("contractDurationID,=J? AND quantity sum(:quantity) ,>1I "6) %></td> </tr> <tr> <td><%= OdemandLevels.where ("contractDurationID,=,?",4).sum(:quantity) <td><%= OdemandLevels.where ("contractDurationID-= <td><%= OdemandLevels.where("contractDurationID <tr> 111 ( - ( %></td> OdemandLevels.where("contractDuration1D,=,?,ANDquantity,>,11,6).count*11) </tr> - >,5",4).count*5) %></td> ?,5) %></td> .sum(:quantity) ,,7?",6).sum(:quantity) %></td> %></td> - <td><%= (CdemandLevels.where ("contractDurationIDu=u?uANDuquantityu>u5" OdemandLevels.where("contractDurationIDu=,?,ANDquantityu>5'",4).count*5)) contractDurationID,=,?",4).sum(:quantity)) OdemandLevels.where ("contractDurationIDu=,?,ANDuquantityu>u8" ("contractDurationID,=u?uANDuquantityu>u8",5).count*8)) contractDurationIDu=u?u",5).sum(:quantity)) <td><X= ,4).sum(:quantity) - ( - ( (OdemandLevels.where(" %></td> where (OdemandLevels <td><X= / / ,5).sum(:quantity) (CdemandLevels.where(" ></td> (OdemandLevels.where("contractDurationID,=u?uANDuquantityu>,11",6).sum(:quantity) OdemandLevels where ("contract DurationIDu=u?uANDuquantityu>uI1",6).count*11) contractDurationIDu=u?",6).sum(:quantity)) - ( (CdemandLevels.where(" %></td> </tr> </table> <h2>Unit Price</h2> <table> <tr> <td>12 mo</td> <td>6 mo</td> <td>3 mo</td> <td>Fixedl</td> <td>Fixed2</td> <td>Fixed3</td> </tr> <tr> - <td><%=243.2 14.7*12 <td><%=243.2 - 14.7*6 %></td> <td><%=243.2 - 14.7*3 %></td> <td><%= quantity) (243.2 - %></td> 14.7*12)*(1-((CdemandLevels.where("contractDurationID,=,?uANDuquantityu>u5",4).sum(: (OdemandLevels.where("contractDurationIDu=?u - ,4) .sum(:quantity)))) where("contractDurationIDu=u?" contractDurationID=u?uANDquantityu>u5" ANDquantityu>u5" ,4).count*5)) <td><%= quantity) (243.2 - ,5).sum(:quantity)))) quantity) + / + / </tr> </table> Comparisons</h2> <table> <tr> <td> </td> Average Unit Price</td> <td>6 mo Average Unit <td>3 mo Price</td> Average Utilization</td> <td>Fixedl + Unit Price</td> <td>Fixed2 + 3mo Avg Unit Price</td> <td>Fixed3 + 3mo Avg Price</td> 3mo Avg Unit </tr> <tr> mo 14.7*3)*((OdemandLevels.where(" Average - - 5) .sum(:quantity))) %></td> ,6).count*11)) / UP</td> <td><%= (243.2 - 14.7*12) / (243.2 - 14.7*12) <td><%= (243.2 - 14.7*12) / (243.2 - 14.7*6)X></td> <td><%= (243.2 - 14.7*12) / (243.2 - 14.7*3)%></td> %></td> 112 (OdemandLevels . 14.7*3)*((OdemandLevels.where(" (OdemandLevels.where("contractDurationID,=,?u (OdemandLevels.where("contractDurationID,=u?" td> mo (243.2 quantity) contractDurationIDue?,ANDuquantityu>11",6).Sum(: <td>12 - (OdemandLevels.where("contractDurationIDu=?u", ,6).sum(:quantity)))) ANDuquantityu>A1",6).count*11)) <h2>Relative Price =u?, %></td> (OdemandLevels.where("contractDurationIDu=u? - (OdemandLeveIs.where ("contractDurationIDu=,?uANDuguantityu>11" - 4). sum(:quantity))) 14.7*12)*(1-((OdemandLevels.where("contractDurationID,=uuANDuquantityu>A11",6).sum(: where("contractDurationIDu=?u" <td>12 (243.2 ,5).sum(:quantity) ANDquantity,>,8",5).count*8)) - (OdemandLevels.where("contractDurationID - (OdemandLevels.where("contractDurationID,=u?" contractDurationID,=,?,ANDquantity>,8" (243.2 (OdemandLeveIs. (demandLevels where("contractDurationIDu=u~uANDuquantity,>,8",5).sum(: where(",ontractDurationID,=uuANDuquantity,>,8",5).count*8)) / ((demandLevels. where("contractDurationID=u?u" <td><%= ,4).sum(:quantity) / 14.7*3)*((OdemandLevels.where(" - 14.7*12) *(-( (OdemandLevels - / ANDuquantityu>.5",4).count*5)) (243.2 + ,6).sum(:quantity))) %></ <td><%= (243.2 - 14.7*12) ,4).sum(:quantity) / ((243.2 14.7*12)*(1-((OdemandLevels.where("contractDurationID - / OdemandLevels.where ("contractDurationID,=-7",4).sum(:quantity)))) contractDurationIDu- ?,,ANDquantity,>,5",4).sum(:quantity) ANDuquantity,>,5",4).count*5)) <td><%= (243.2 - 14.7*12) ,5).sum(:quantity) / ((243.2 (OdemandLevels.where("contractDurationID,=,?, - (OdemandLevels.where("contractDurationID=,?",4).sum(:quantity))))%></td> - 14.7*12)*(1-((QdemandLevels.where ("contractDurationID,=,?,ANDuquantity / (OdemandLevels.where("contractDurationID,=,?.ANDquantity,>,8",5).count*8)) - ANDquantity>,8",5).count*8)) - 14.7*12) / ((243.2 ( 14.7*3)*((CdemandLevels.where(" - / + "contractDurationID,=-?,ANDuquantity,>,8",5).sum(:quantity) (243.2 (243.2 + OdemandLevels.where ("contractDurationID=UU",5).sum(:quantity)))) <td><%= .=u?,ANDOquantityJ>,5" (OdemandLevels.where("contractDurationID,=?,ANDuquantityu>5,4).count*5)) - (243.2 - 14.7*3)*((CdemandLevels.where( demandLevels.where("contractDurationIDu=u? ( - >e8" ( / (OdemandLevels.where("contractDurationID=a?",5).sum(:quantity))))></td> - 14.7*12)*(1-((QdemandLevels.where ("contractDurationID,=u?,ANDuquantity,>,11 ",6).sum(:quantity) (demandLevels where("contractDurat ionID/=(?uANDquantity,>,11",6).count*11)) / ( + (243.2 - 14.7*3)*((QdemandLevels.where( OdemandLevels.where('contractDurationID,=,?, 6) .sum(:quantity)))) 1",6).sum(: "contractDurationID,=,?,ANDquantity,>, ANDuquantity,>211",6).count*11)) / quantity) - (OdemandLevels.where("contractDurationID,=u?, (OdemandLevels.where("contractDurationIDj=?e",6).sum(:quantity))))%></td </tr> <tr> <td>6 mo Average UP</td> <td><%= %></td> <td><%= (243.2 - 14.7*6) / (243.2 - <td><%= (243.2 - 14.7*6) / (243.2 - <td><%= (243.2 - 14.7*6) / ((243.2 ,4).sum(:quantity) OdemandLevels 14.7*6)%></td> 14.7*3)%></td> 14.7*12)*(1-((QdemandLevels.where ("contractDuration1D,=,?,ANDjquantity,>,5" - (OdemandLevels.where("contractDurationID=?,_AND.quantityJ>u5",4).count*5)) - where("contractDurationIDI=L?",4).sum(:quantity) contractDurationID,=,?UANDuquantity,>,5",4)sum(:quantity) ANDuquantity>b5" ,4).count*5)) <td><%= (243.2 - 14.7*6) / ((243.2 (OdemandLevels.where("contractDurationID-, - OdemandLevels.where ("contractDurationID=,?-,5).sum(:quantity)))) ANDuquantityj>u8",5).count*8)) <td><%= (243.2 - 14.7*6) ,6).sum(:quantity) + / / ((243.2 (243.2 - 14.7*3)*((QdemandLevels.where( (OdemandLevels.where("contractDurationIDu=u?u",5)sum(:quantity))) )></td> ?,ANDuquantity,>,11" / (OdemandLevels.where("contractDurationID,=-?.ANDwquantity,>,11",6).count*11)) - + "contractDuration1DI=L?,ANDquantity>u11",6).sum(:quantity) 11",6).count*l1)) / - (OdemandLevels.where 8" ( (OdemandLevels.where("contractDurationID=,?, - 14.7*12)*(1-((OdemandLevels.where("contractDurationIDO= - 7 AND.,quantity,> / OdemandLevels.where ("contractDurationID,=u?.",6) .sum(:quantity)))) ANDquantity,>, 7 (OdemandLevels.where("contractDurationID=?,ANDquantity§>'8",5).count*8)) "contractDurationID,=,?,ANDuquantityu>u8",5).sum(:quantity) ( ?",4).sum(:quantity))))%></td> 14.7*12)*(1-((OdemandLevels.where("contractDurationID,=r, - ,5).sum(:quantity) / 14.7*3)*((demandLevels.where(" - (OdemandLevels.where("contractDurationID,=? - / (243.2 + (243.2 - ( 14.7*3)*((QdemandLevels.where( (OdemandLevels.where("contractDurationIDu=u?, ("contractDurationID,=-?u",6).sum(:quantity))))%></td </tr> <tr> <td>3 mo Average UP</td> <td><%= %></td> <td><%= %></td> <td><%= (243.2 - 14.7*3) / (243.2 <td><%= (243.2 - 14.7*3) / ((243.2 ,4).sum(:quantity) - 14.7*3)X></td> 14.7*12)*(1-((demandLevels.where("contractDurationID=u?,ANDuquantity>,5" - (OdemandLevels.where("contractDurationID,=u?,ANDuquantity,>,5",4).count*5)) - OdemandLevels.where("contractDurationIDu=?", 4). sum(:quantity)))) contractDurationIDule?,ANDquantityu>,5",4).sum(:quantity) ANDuquantityU>a5",4).count*5)) <td><X= (243.2 - 14.7*3) ,5).sum(:quantity) / ((243.2 OdemandLevels.where("contractDurationID=,?",5).sum(:quantity)))) "contractDurationIDu=,?,ANDuquantity,>,8",5).sum(:quantity) ANDuquantityu>u8",5).count*6)) <td><%= (243.2 - ,6).sum(:quantity) 14.7*3) / - ((243.2 / .ANDuquantity,>,8" - + (243.2 - (OdemandLevels.where - ( ("contractDurationID,=u?u 14.7*12)*(1-((OdemandLevelswhere("contractDurationID,=,?,ANDLquantity,>A11" (OdemandLevels.where("contractDurationIDu=,?,ANDuquantityu>,11",6).count*11)) sum(:quantity)))) =,?,AND.quantity ANDquantjty>uJ11",6).count*11)) / 14.7*3)*((@demandLevels.where( (CdemandLevels.where("contractDurationID=?",5).sum(:quantity))))%></td> OdemandLevels.where("contractDurationID,-=?j,6). "contractDurationID 7 (OdemandLevels.where("contractDurationIDU=uUANDquantityu>u8",5).count*8)) - ( (OdemandLevels.where("contractDurationID,=?",4).sum(:quantity))))%></td> 14.7*12)*(1-((OdemandLevels.where("contractDurationID=, - / 14.7*3)*((CdemandLevels.where(" - (CdemandLevels.where("contractDurationID=.,?, - / (243.2 + / >, 11",6).sum(:quantity) + - (243.2 - / ( 14.7*3)*((QdemandLevels.where( (4demandLevels.where("contractDurationID,,=?, (OdemandLevels.where("contractDurationIDu=?,,6).sum(:quantity))))%></td 113 <tr> <td>Fixedl mo Average <td><%= /></td> <td><%= %></td> <td><%= (></td> <td><X= ((243.2 UP</td> 14.7*12) - where *(1 -( (OdemandLevelIs (OdemandLevels.where("contractDurationIDu=u? / (243.2 + u>uS",4).sum(: Dur at ionIDu=u?u AND, quantity / ANDuquantityL'>S5",4).count*5)) contractDurationID,=,?",4).sum(:quantity)))) ?uANDuquantityu>u5",4).sum(:quantity) count*5)) ("contract 14.7*3)*((QdemandLevels.where("contractDurationID,=, - / ,4).sum(:quantity)))) (OdemandLevels.where("contractDurationID=u,?" (243.2 + quantity) - ((243.2 (OdemandLevels.where("contractDurationID - ((243.2 =j? ANDquantity,>,5" ,4).count*5)) contractDurationIDu=?" ationIDu=uuANDquantityu>u5",4).count*5)) ,4).sum(:quantity)))) ?uANDuquantityu>u5",4).sum(:quantity) (243.2 + contractDurat ion D,=,?,ANDquantityu>uV",5).count*8)) sum(:quantity)))) - + (243.2 - / / 5).sum(:quantity) contractDurationIDu=,?",4).sum(:quantity)))) + - (243.2 (243.2 + - (OdemandLevels. 4).sum(:quantity) / - (OdemandLevels.where(" 14.7*3)*((CdemandLevels.where("contractDurationIDu=, - / ,4).sum(:quantity)))) / contractDurationIDu=,?,ANDuquantity,>u11",6).count*11)) .where(" / ?uANDquantityu>u8",5).count*8)) OdemandLevels.where("contractDurationID,=u?uANDuquantity,>,11" sum(:quantity)))) ,5) )%></td> (OdemandLevels.where("contractDurationID,=-?" (:quantity) (OdemandLevels.where(" - (OdemandLevels.where("contractDurationID,= - ,4). 14.7*12)*(1-(( - (OdemandLevels.where("contractDurationID=uu" (OdemandLevels.where("contractDurationlDu= ?,ANDquantity>,5" ,4).sum(:quantity) / ((243.2 14.7*12) *(1-((demandLevels4where("contractDurationI.D=umANDquantityu>,5" - - (OdemandLevels.where(" ("contractDurationIDu=,?uANDuquantityu>u5" (OdemandLevels.where("contractDurationID,=,?,ANDquantity,>,5",4).count*5)) count*5)) (cdemandLevels. where("contractDurationID,=,?,ANDquantityu>u8",5).sum 14.7*3)*( (demandLevels where("contractDurationIDu=u?u" ,5).sum(:quantity))) ((243.2 / ,4).sum(:quantity)))) OdemandLeveIs.where("contractDurationIDU=?uANDuquantityu>8", <td><%= / 14.7*3)*((OdemandLevels.where ("contractDurationIDu=, - (OdemandLevels.where - (OdemandLevels.where ("contractDurationIDu?" (:quantity) 4). sum 4).sum(:quantity))))%></td> where("contractDur / (OdemandLevels.where(" - (edemandLevels.where("contractDurationID,=u?" 14.7*12)*(1-((OdemandLevels.where("contractDurationIDu=u?uANDquantityU>15",4).sum(:quantity) - (/demandLevels count*5)) ,4). 14.7*12)*(1-(( - 14.7*3)*((OdemandLevels.where("contractDurationID,=,?,ANDquantity,>,5",4).sum(: where("contractDurationIDu=u?" <td><%= / DurationID=u?ANDuquantityu>u5",4).count*5)) (:quantity)))) - (OdemandLevels.where("contractDurationID,=u?uANDuquantityu>u5" - OdemandLevels.where("contractDurationIDu=eu7ANDuquantityu>,5",4).sum(:quantity) contract quantity) (CdemandLevels.where(" ?,ANDquantityu>,5" ((243.2 ,6).sum(:quantity) - ,4). 14.7*12)*(1-(( - (OdemandLevels.where(" (OdemandLevels.where('contractDurationIDu=u?u" 6). 14.7*3)*((OdemandLevels.where("contractDurationIDu=,?,ANDuquantityu>u I11",6).sum / (CdemandLevels.where("contractDurationIDu=u?,ANDuquantityu>,11",6).count*ll)) contract Duration lDw=u?u",t6).sum(: quant it (OdemandLevels y)) ) )></td> </tr> <tr> <td>Fixed2 mo Average <td><%= X></td> <td><%= %></td> <td><%= %></td> <td><%= %></td> <td><%= ((243.2 UP</td> where("contractDurationID,=,?,ANDuquantity,>u8",5).sum(:quantity) 14.7*12)-*(1-((demandLevels - (/demandLevels where("contract DurationIDu=u?uANDquantity(>C8",5).count*8)) contractDurationID,=u?,",5).sum(:quantity)))) + (243.2 / 14.7*3)*((OdemandLevels.where("contractDurationIDDu= - u?,ANDquantity,>,8",5).sum(:quantity) - (OdemandLevels.where("contractDurationID,=,?,ANDquantityI>8",5). count*8)) / (OdemandLevels.where("contractDurationIDI=,? " ,5).sum(:quantity)))) where("contractDurationID,=,? OdemandLevels ANDuquantity,>,8",5).sum(:quantity) / contractDurationID,=u?uANDLquantityu>u8",5).count*8)) sum(:quantity)))) (:quantity) where <td><%= - ("contract ((243.2 + (243.2 - 14.7*3) *((demandLevels contractDurationIDu=u?,",5).sum(:quantity)))) + ,luANDquantity,>,8",5).sum(:quantity) - (243.2 contractDurationIDu=u?uANDuquantity,>,11",6).count*11)) + - (243.2 (OdemandLevels - 14.7*12)*(1-(( ,5) ,5).count*8)) / (OdemandLevels. ,5).count*8)) / ,5).sum(:quantity) - (OdemandLevels.where(" 14.7*3)*((OdemandLevels.where("contractDurationID,= - (OdemandLevels.where("contractDurationIDL=u?uANDuquantityU>L8",5). (OdemandLevels.where ("contractDurationlDu=u?u" sum(:quantity)))) - I DL?uANDuquantityL>U8",5).sum / ,5).sum(:quantity)))) where("contractDurationIDu~u?uANDuquantityu>ull",6).sum(:quantity) ,demandLevels (:quantity) (odemandLevels.where(" 14.7*12)*(1-((OdemandLevels.where("contractDurationIDu=u?uANDuquantityu>u8" - / ((243.2 - )%></td> (OdemandLevels.where("contractDurationIDu=,?ANDquantity,>,8' count*8)) / (OdemandLevels.where("contractDurationIDu=u?u" where("contractDuration (CdemandLevels.where("contractDurationIDu=u?uANDuquantityu>u8" Dur at ion IDu=,?," ,5).sum(: quantity))) - (OdemandLevels.where(" / ((243.2 - - 14.7*12)*(1-(( (OdemandLevels.where(" (OdemandLevels.where("contractDurationIDu=?,",6). 14.7*3)*((CdemandLevels.where("contractDurationIDu=,?uANDquantity,>,11",6).sum where("contractDurat ionID=uuANDuquantityu>u11" 114 ,6).count*11)) / (OdemandLevels ?,",6).sum(:quantity))))%></td> .where("contractDurationID,= </tr> <tr> <td>Fixed3 mo Average <td><%= %></td> <td><%= %></td> <td><.= %></td> <td><%= %></td> UP</td> <td><%= %></td> <td><X= %></td> 1.0 </tr> </table> <h2>Relative Price Times Relative Utilization</h2> <table> <tr> <td> </td> <td>12 mo</td> <td>6 mo</td> <td>3 mo</td> <td>Fixedl</td> <td>Fixed2</td> <td>Fixed3</td> </tr> <td>12 <td><%= mo Average UP</td> (OdemandLevels.where("contractDurationIDJ=7?" ,=l?", / 3).sum(:actual-bw)) / ,3).sum(:quantity) OdemandLevels.where("contractDurationID (OdemandLevels.where("contractDurationID_= / ?",3).sum(:quantity) OdemandLevels %></td> / OdemandLevels.where("contractDurationlID <td><= (OdemandLevels.where("contractDurationlD,=,?",3).sum(:quantity) / OdemandLevels / (OdemandLevels.where("contractDurationID=,?" ,2).sum(:quantity) 3). sum(:actual-bw)) ,=,?", )/((243.2 .where ("contractDurationlD,=,?", 3).sum(:actualbw) .where ("contractDurationID,=,,?', 2).sum(:actual-bw))/((243.2 <td><%= (OdemandLevels.where("contractDurationID=u?" =?, / 3).sum(:actualbw)) - 14.7*12) / ,3).sum(:quantity) - 1).sum(:actual-bw))/((243.2 / 3).sum(:actual-bw)) / (243.2 (243.2 (:quantity)))) / 4).sum(:actual-bw))/((243.2 - quantity) - - / 3).sum(:actual-bw)) OdemandLevels.where ("contractDurationID 14.7*12) / contractDurat where(" <td><Y.= + - ( / ?",3).sum(:quantity) - - / QdemandLevels.where + - / ((243.2 =?", - (OdemandLevels.where(" ID ID. (OdemandLevels.where("contractDuration .sum(: quantity)))) ?,5). >,8",5).count*8)) / (OdemandLevels. )%></td> / OdemandLevels.where("contractDuratioIlD 6). sum(:actual-bw))/((243.2 - ,ANDuquantity,> / 14.7*12) / / ((243.2 11",6).sum(:quantity) - (ademandLevels.where(" (OdemandLevels.where("contractDurationID,=,? 14.7*3)*((OdemandLevels.where(" contractDurationID,, %></td> =,?",j6). sum(:quantity))))) </tr> </table> 115 OdemandLevels 14.7*12)*(1-(( ?,AND quantity (OdemandLevels.where("contractDurationID=,?aAND,,quantity,>.11",6).count*11)) .where(" contractDuration OdemandLevels 14.7*12)*(1-(( (OdemandLevels.where("contractDurationID,=?",6).sum(:quantity) ("contractDurationID,=' (243.2 - / contractDurationlD,,u=?ANDuquantity,>u11",6).count*11)) sum(:quantity)))) (CdemandLevels. 14.7*3)*((QdemandLevels.where("contractDurationID,.=u7ANDuquantityu>.8",5).sum ?,5) .where("contractDurationID (:quantity) 4) .sum(: / / demandLevels.where("contractDurationlD,=U?,ANDuquantity contractDurationID,= 3).sum(:actual-bw)) =&?",4).sum OdemandLevels.where("contractDuration ID 14.7*12) (OdemandLevels.where("contractDurationIDu=,?",3).sum(:quantity) ,=,?", (OdemandLevels.where(" ("contractDurationID ("contractDurationID,=,?,ANDquantity,>,8",5).sum(:quantity) (243.2 OdemandLevels 14.7*12)*(1-(( (OdemandLevels.where("contractDurationID,=,?",5).sum(:quantity) ionIDu=,?uANDquantity,>,8",5).count*8)) sum(:quantity)))) (:quantity) - - (OdemandLevels.where 5).sum(:actual-bw))/((243.2 where / 4) .sum(:quantity) ((243.2 )%></td> 4). sum(: quantity)))) .where("contractDurationID,=,?", OdemandLevels OdemandLevels %></td> 14.7*3)) (OdemandLevels.where("contractDurationID,=,?,ANDuquantityu>,5",4).count*5)) (OdemandLevels.where("contractDurationID,= ,=,?", - 14.7*3)*((CdemandLevels.where ("contractDurationID,=,?ANDLquantityL>5" where("contractDurationIDu=1 ?" <td><%= / ,ANDquantity,>5",4).count*5)) (243.2 + 14.7*6))%></td> - (243.2 OdemandLevels.where("contractDuration ID,=,?AND.quantityu>u5",4).sum(:quantity) 7 14.7*12)) / / (OdemandLevels.where("contractDurationID,=?", .where ("contractDurationIDU-,?", contractDurationID=,? - OdemandLevels.where("contractDurationID 14.7*12) ("contractDurationIDu=,?",3).sum(:quantity) (OdemandLevels.where / (OdemandLevels.where("contractDurationID=?",1).sum(:quantity) .where ("contractDurationID,=u?", <td><%= 14.7*12) - ",6). ,1P",6).sum / (OdemandLevels <h2>Avg Price / Utilization</h2> <table> <tr> <td>12 mo</td> <td>6 mo</td> <td>3 mo</td> <td>Fixedl</td> <td>Fixed2</td> <td>Fixed3</td> </tr> <tr> <td><%= (243.2 OdemandLevels.where <td><%= 14.7*12)/(OdemandLevels.where("contractDurationID,=,?" - ("contractDurationID,=,?", (243.2 3).sum(:actual <td><%= (243.2 2).sum(:actual-bw)) <td><%= ((243.2 ,2).sum(:quantity) / ,).sum(:quantity) / %></td> 14.7*3)/(CdemandLevels.where("contractDurationIDu=u?" - 1).sum(:actual-bw)) ("contractDurationIDu=?", / 3).sum(:quantity) %></td> 14.7*6)/(OdemandLevels.where("contractDurationID,=,?" - OdemandLevels.where("contractDurationIDu=u?", OdemandLevels.where bw)) %></td> 14.7*12) *(4-((demandLevels)where("contractDurationIDu=)?uANDuquantity.>u5",4) - (OdemandLevels where("contractDuration IDU=UANDuquantity,>,5",4).count*5)) / ( OdemandLevels.where ("contractDurationID=u?" ,4).sum(:quantity)))) + (243.2 - 14.7*3)*((OdemandLevels.where(" sum(:quantity) - contractDurationIDu=u? ANDquantity la5",4).sum(:quantity) ANDuquantityu>,5",4).count*5)) / (OdemandLevelswhere("contractDurationIDu=,?, - (OdemandLevels.where("contractDurationID OdemandLevels.where("contractDurationIDu=,?",4).sum(:quantity) 4).sum(:actual-bw)) <td><%= sum(:quantity) - 14.7*12) *(5-((demandLevels)where("contractDurationIDu=)?uANDuquantityu>u8" OdemandLevels.where("contractDurationIDu=?j "contractDuration I D=?,ANDuquantityu>u8",5).sum(:quantity) ANDuquantityI>,8" ,5).count*8)) / <td><%= "contract - - 14.7*12)*(1-( / (OdemandLevels.where ,6).sum(:quantity) %></td> </table> Levels</h2> <table> <tr> <th>id</th> <th>timeStepID</th> <th>satelliteID</th> <th>bandwidth</th> <th>cost</th> <th>contractDuration</th> </tr> in ,5) .sum(:quantity))))/( OdemandLevels.where("contractDurationIDu=u? OsatLevels where("contractDurationIDu=u?uANDuquantity ,6).sum(:quantity)))) DurationIDu=?uANDuquantityu>u I"l,6).sum(:quantity) satLev 14.7*3)*((OdemandLevels.where( DurationID=?uANDquantityu>uI1",6).count*11)) </tr> <% for / ,5).sum(:quantity) (demandLevels OdemandLevels.where("contractDurationIDI=U?" <h2>Satellite - (OdemandLeveIs.where("contractDurationIDu=u?" (OdemandLevels 6).sum(:actual-bw)) (243.2 5). ( %></td> ((243.2 ANDuquantity,>u11",6).count*l1)) ", + / (OdemandLevels.where("contractDurationID,=,?, - where(" contract OdemandLevels.where("contractDurationIDu=?u" .sum(:quantity) ?uANDuquantityu>u8" ,5).count*8)) ',5).sum(:quantity)))) OdemandLevels.where("contractDurationID=U?" 5).sum(:actualbbw)) =u?",4).sum(:quantity))))/( OdemandLevels.where("contractDurationIDu=u? X></td> ((243.2 (OdemandLevels.where("contractDurationIDu= - / %> <tr> <td><%= satLev.id %></td> <td><%= satLev.timeStepID X></td> <td><%= satLev.satelliteID %></td> <td><%= satLev.bandwidth %></td> <td><%= satLev.cost %></td> 116 + - (243.2 / - >uI1",6) ( 14.7*3)*((OdemandLevels.where( (OdemandLevels.where("contractDurationID,=,?, ("contractDurationID=?u" / 6) .sum(:quantity))))/( OdemandLevels.where("contractDurationIDu=,? <td><%= satLev.contractDurationID X></td> </tr> <% end %> </table> <%= will-paginate(OsatLevels) <h2>Demand by Region %> and TimeStep</h2> <table> <tr> <th>id</th> <th>timeStepID</th> <th>regionID</tb> <th>quantity</th> </tr> <% for demand in OdemandLevels V.> <tr> <td><%= demand.id %></td> <td><%= demand.timeStepID %></td> <td><%= demand.regionID %></td> <td><%= demand.quantity %></td> </tr> <% end %> </table> <%= will-paginate(OdemandLevels) B.2 class def %> Controller SatLevelsController < ApplicationController index QlastSim = Simulation.last 11= QlastSim params [:simulation] OcurrentSim = Simulation.find-by-id(params[:simulation]) Qsats=QlastSim.satellites OtimingRuns= OsatLevels per-page => = 30, OdemandLevels per-page if => 30, QlastSim.timing-run SatLevel.joins(:time-step).where :page => =Demand.joins(:time-step).where("time-steps.simulationID,=I?", :page => (ecurrentSim Osats = ("time-steps.simulationID,=?", = ClastSim.id ).paginate(: OlastSim.id ).paginate(: params[:page]) params[:page]) Simulation.find-by-id(params[:simulation])) QcurrentSim.satellites OtimingRuns= OcurrentSim.timing-run QsatLevels paginate (:per-page => = SatLevel.joins(:time-step).where(t ime 30, CdemandLevels paginate (:per-page => 30, :page => steps =Demand.joins (:timeestep).where ("time_steps :page => simulationID,=,?", OcurrentSim.id ). simulation1D,=_?", OcurrentSim.id ) params[:page]) params[:pagel) end end 117 end B.3 class Models ContractDuration has-many < ActiveRecord::Base :sat-level end class Demand ActiveRecord::Base < belongs-to :region belongs-to :time-step, foreign-key: def self.atTimeStepRegConActual(ts, 'timeStepID' reg, contract) ts where("timeStepIDu=,?,ANDuregionIDU=U?uANDcontractDurationID=?", , reg, contract).sum(: actual-bw) end def reg, self.atTimeStepRegConQuantity(ts, contract) ts, where("timeStepID,=,?,ANDregionIDu=u?,ANDcontractDurationID,=,? reg, contract).sum(: quantity) end end class OptionsCost < ActiveRecord::Base belongs-to :contact-duration, belongs-to :time-step, foreign-key: 'timeStepID' belongs-to :satellite, foreign_key: 'satelliteID' def self.cumCost(ts, where foreign-key: contract, 'contractDurationID' satID) (" timeStepIDu=coANDncontractDurationID,=,7,ANDusatelliteIDu=? ts contract, satID).sum(: cumTotalC) end end class Region < ActiveRecord::Base has-many :demand has-many :satellite-region end class RunCost < ActiveRecord::Base belongs-to def :simulation self.onSim(sim) where("simulationID; ?",sim) end def self.countBetween(lower, where("cumCost upper, contract) >u,?,ANDcumCostU<,7,ANDcontractDurationIDL=L?", end end 118 lower , upper, contract).count class SatLevel ActiveRecord::Base < 'contractDuration foreign.key: belongs-to :contact-duration, belongs-to :time-step, foreign-key: 'timeStepID' belongs-to :satellite, foreign-key: 'sateliteID' def ID' self.atTimeStep(ts) where("timeStepIDu=,?" ts).sum(:bandwidth) , end def self.atTimeStepSat(ts, satID, contract) where("timeStepID=?,ANDsatelliteID,=,?,ANDcontractDurat ionJD,_?", ts, satID, contract).sum(: bandwidth) end def self.atTimeStepCumCost(ts, contract) contractDurationID,='?",ts, where("timeStepID,<=,,?AND contract).sum(:cost) end def self.CountAtCosts(lower, upper) >=,?,ANDecost,<?", where("cost lower , upper).count end def .cumCost (ts self contract , where("tireStepID,, , satID) ,AND contractDurationiD-,?,AND cumCost) end end class SatelliteRegion < ActiveRecord::Base belongs-to :Satellite belongs-to :region end class Satellite < has-many ActiveRecord::Base :satjlevel, 'satLevelID' foreign-key: end class Simulation < ActiveRecord::Base foreign-key: has-many :time-step, has-many :satellites, has-many :run-cost has-many :timingrun, , timeSteplD' foreign-key: 'simulationID' 'simulationID' foreign-key: foreign-key: 'simulationID' end class TimeStep < ActiveRecord::Base belongs-to :simulation has-many :demand has-many :sat-level, def foreign-key: 'timeStepID' self.stepsOnLastSim where("simulat ionID, ,?e,Simulation.last) end def self.stepsOnSim (sim) where("simulationIDe. ,?_, sim) 119 satelliteID=?" , ts, contract , satID).sum(: end def self.CountAtSatCosts(lower, joins(: satllevel) upper, where(" contract) cost,>=prANDcostu<?aANDcontractDurationID,=,? lower, contract).count end def self.countAtSatLevel(lower, joins(: sat-level). contractDurationID,=u?", upper, satID, contract) where ("bandwidth,>=? lower, upper, satID, uANDubandwidthu<u? contract).count end end class TimingRun < ActiveRecord::Base end B.4 Database Migrations class CreateSimulations < ActiveRecord::Migration def change create-table t.string :simulations do Iti :name t .timestamps end end end class def CreateSatLevels < ActiveRecord::Migration change create-table :sat-levels do t.integer :timeStepID t.integer :satelliteID t.float :bandwidth t.float :cost t.integer Iti :contractDurationID t .timestamps end end end class def CreateTimeSteps < ActiveRecord::Migration change create-table :time-steps do Iti t.integer :run t.integer :period t.integer :simulationID t.timestamps 120 ANDsate11iteI D=,?uAND, upper end end end class def CreateDemands < ActiveRecord::Migration change create-table :demands do t.integer :timeStepID t.integer :regionID t.float Iti :quantity t.timestamps end end end class def CreateRegions < ActiveRecord::Migration change create-table t.string :regions do Iti :name t.timestamps end end end class < CreateContractDurations def ActiveRecord::Migration change create-table :contract t.integer durations do Iti :months t.timestamps end end end class CreateSatellites def < ActiveRecord::Migration change create-table t.string :satellites do Iti :name t.integer :capacity t.timestamps end end end class CreateSatelliteRegions def < ActiveRecord::Migration change create-table :satellite-regions t.integer :satelliteID t.integer :regionID do Iti t.timestamps end end end 121 class AddActualBwToDemand < ActiveRecord::Migration def change add-column :demands, float :actual-bw, end end class AddSimulationIdToSatellite < ActiveRecord::Migration def change add-column :satellites, simulationID, integer end end class AddContractDurationIdToDemands def < ActiveRecord::Migration change add-column :demands, :contractDurationID, :integer end end class def CreateRunCosts < ActiveRecord::Migration change create-table t.float :run-costs do ti :cumCost t.integer :simulationID t.integer :run t.timestamps end end end class AddContractDurationIdToRunCosts < ActiveRecord::Migration def change add-column :run-costs, :contractDurationID, integer end end class AddCumCostToSatLevels def < ActiveRecord::Migration change add-column :sat-levels, :cumCost , :float end end class CreatefptionsCosts < ActiveRecord::Migration def change create-table t.integer :options-costs do Iti :timeStepID t.integer :optionsExecuted t.integer :optionsPurchased t.float :reservationPrice t.float :executionPrice t.float :optionsCost t.float :cumOptC t.float :excessCost t.float :cumTotalC t.integer :contractDurationID t.timestamps end end end 122 class def AddSatelliteIdToOptionsCosts < ActiveRecord::Migration change add-column :options-costs, satellitelD, integer end end class def CreateTimingRuns < ActiveRecord::Migration change create-table :timing-runs t.integer :simulationID t.integer :run t.integer :numPeriods t.integer :numSats t.integer :numSatLevels t.integer :numReg t.integer :numNodes t.integer :numSteps do Iti t.timestamps end end end 123 124 Bibliography [1] General Services Administration. Indefinite Delivery, Indefinite Quantity Contracts. 2012. URL: http://www.gsa.gov/portal/content/103926 (visited on 04/10/2012). [2] Defense Information Systems Agency. Modifications to the Defense Information Systems Network (DISN) Satellite Transmission Services. 2010. URL: https: //www. fbo . gov/ index?s=opportunity&mode=form&tab=core&id= dc931c9adb0017bfc22f4de97e7ee2ea. [3] European Space Agency. Satellite Frequency Bands. 2013. URL: http: //www. esa. int/OurActivities/TelecommunicationsIntegratedApplications/ Satellite_frequencybands (visited on 04/10/2014). [4] Tim Bonds et al. Employing Commercial Satellite Communications: Wideband Investment Options for the Department of Defense. Tech. rep. RAND, 2000. [5] Neil F. Albert. Taking Advantage of Opportunities for Commercial Satellite Communications Services: Report to the Secretary of Defense. Tech. rep. Defense Business Board, 2013. [6] Amazon. Amazon Prime Air. 2013. URL: http: //www. amazon. com/b?node= 8037720011 (visited on 04/15/2014). [7] Elisabeth Bumiller. Obama Puts His Stamp on Strategy for a Leaner Military. NY Times. Jan. 5, 2012. URL: http: //www.nytimes. com/2012/01/06/us/ obama- at-pentagon-to- outline- cuts-and-strategic- shif ts.html?_r=0 (visited on 05/10/2014). 125 [8] CCJ. TransCore:Satellite network achieved 99.992% uptime in 2007. 2008. URL: http: //www. ccjdigital. com/transcore- satellite -network- achieved- 99992-uptime-in-2007-2/ (visited on 04/13/2014). [91 DISA. FY 2010 COMSATCOM Annual Usage Report Released to DoD Stakeholders. 2012. URL: http://www.disa.mil/Services/SATCOM/ComsatcomServices/Scoop-Newsletter/2012-10/FY2010-COMSATCOM-Annual-UsageReport (visited on 04/12/2014). [10] DoD. "17.2. Options". In: Federal Acquisition Regulation. Ed. by DoD. 2014. URL: http: //www. acquisition .gov/far/html/Subpart%2017 _ 2. html (visited on 05/12/2014). [111 Defense FAR. "Part 252 - Solicitation Provisions and Contract Clauses". In: Defense FederalAcquisition Regulation Supplement. Ed. by Defense FAR. 2012. URL: www . acq . osd . mil / dpap / dars / df ars / doc / 252239 . doc (visited on 04/10/2014). [12 Frost and Sullivan. Commercial Geostationary Satellite Transponder Markets for Latin America. 2003. URL: http : / / www . frost . com / prod / serviet / report -brochure .pag?id=A397-01-00-00-00 (visited on 04/14/2014). [13 Futron. 2010 Futron Forecast of Global Satellite Services Demand Overview. 2010. URL: http://www.futron.com/upload/wysiwyg/Resources/Reports/ 2010_FutronForecastOverview.pdf (visited on 04/10/2014). [14] Jacbo Gullish. The North American Satellite Market New Methodology Required... Futron. 2011. URL: http: / /www .satmagazine . com / story . php ? number=1585073081 (visited on 04/10/2014). [15] Xin Huang. "Capacity Planning in a General Supply Chain with Multiple Contract Types Single Period Model". PhD Thesis. Massachusetts Institute of Technology, 2008. 126 [16] Dustin Kaiser. Military Communications A Key Target For Satellite Services. Futron. 2011. URL: http: //www. milsatmagazine. com/story .php?number= 1620673149 (visited on 04/12/2014). [17] Owen Kurtin. FSS and MSS: Blurring the Lines. 2012. URL: http: //www . satellitetoday. com/telecom/2012/05/01/f ss - and-mss -blurring-the - lines/ (visited on 04/12/2014). [18] Patrick Rayerman. "Exploiting Commercial SATCOM: A Better Way". In: Parameters. Winter 03-04 (2003). URL: http: //strategicstudiesinstitute. army.mil/pubs/parameters/articles/03winter/rayerman. htm (visited on 04/10/2014). [19] Shaun Waterman. Drones over U.S. get OK by Congress. Washington Times. 2012. URL: http://www.washingtontimes.com/news/2012/feb/7/comingto-a-sky-near-you/?page=all (visited on 04/11/2014). 127