def small_simulation(): """Solve a simulation with two markets, linear prices, a nonlinear characteristic, a cost characteristic, and an acquisition. """ simulation = Simulation(product_formulations=(Formulation('0 + prices'), Formulation('0 + x'), Formulation('0 + a')), beta=-5, sigma=1, gamma=2, product_data=build_id_data(T=2, J=18, F=3, mergers=[{ 1: 0 }]), integration=Integration('product', 3), xi_variance=0.001, omega_variance=0.001, correlation=0.7, seed=0) clustering_ids = np.random.choice(['a', 'b'], simulation.N) product_data = np.lib.recfunctions.rec_append_fields( simulation.solve(), 'clustering_ids', clustering_ids) return simulation, product_data
def small_blp_simulation() -> SimulationFixture: """Solve a simulation with three markets, linear prices, a linear/nonlinear characteristic, two cost characteristics, and uniform unobserved product characteristics. """ id_data = build_id_data(T=3, J=18, F=3) uniform = 0.001 * np.random.RandomState(0).uniform(size=(id_data.size, 3)) simulation = Simulation( product_formulations=(Formulation('0 + prices + x'), Formulation('0 + x'), Formulation('0 + a + b')), product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'clustering_ids': np.random.RandomState(0).choice(range(10), id_data.size) }, beta=[-5, 1], sigma=2, gamma=[2, 1], integration=Integration('product', 3), xi=uniform[:, 0] + uniform[:, 1], omega=uniform[:, 0] + uniform[:, 2], seed=0) simulation_results = simulation.solve() return simulation, simulation_results, []
def large_simulation(): """Solve a simulation with ten markets, linear/nonlinear prices, a linear constant, a cost/linear/nonlinear characteristic, another three cost characteristics, another two linear characteristics, demographics interacted with prices and the cost/linear/nonlinear characteristic, dense parameter matrices, an acquisition, a triple acquisition, and a log-linear cost specification. """ simulation = Simulation( product_formulations=(Formulation('1 + prices + x + y + z'), Formulation('0 + prices + x'), Formulation('0 + log(x) + a + b + c')), beta=[1, -6, 1, 2, 3], sigma=[[1, -0.1], [0, 2]], gamma=[0.1, 0.2, 0.3, 0.5], product_data=build_id_data( T=10, J=20, F=9, mergers=[{f: 4 + int(f > 0) for f in range(4)}]), agent_formulation=Formulation('0 + f + g'), pi=[[1, 0], [0, 2]], integration=Integration('product', 4), xi_variance=0.00001, omega_variance=0.00001, correlation=0.9, linear_costs=False, seed=2) clustering_ids = np.random.choice(['a', 'b', 'c', 'd'], simulation.N) product_data = np.lib.recfunctions.rec_append_fields( simulation.solve(), 'clustering_ids', clustering_ids) return simulation, product_data
def small_nested_blp_simulation() -> SimulationFixture: """Solve a simulation with five markets, linear prices, a linear/nonlinear characteristic, another linear characteristic, three cost characteristics, and two nesting groups with different nesting parameters. """ id_data = build_id_data(T=5, J=18, F=3) simulation = Simulation( product_formulations=(Formulation('0 + prices + x + z'), Formulation('0 + x'), Formulation('0 + a + b + c')), product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'nesting_ids': np.random.RandomState(0).choice(['f', 'g'], id_data.size), 'clustering_ids': np.random.RandomState(0).choice(range(10), id_data.size) }, beta=[-5, 1, 2], sigma=2, gamma=[2, 1, 1], rho=[0.1, 0.2], integration=Integration('product', 3), xi_variance=0.001, omega_variance=0.001, correlation=0.7, seed=0) simulation_results = simulation.solve() return simulation, simulation_results, []
def small_nested_logit_simulation() -> SimulationFixture: """Solve a simulation with four markets, linear prices, two linear characteristics, two cost characteristics, and two nesting groups with different nesting parameters """ id_data = build_id_data(T=4, J=18, F=3) simulation = Simulation( product_formulations=(Formulation('0 + prices + x + y'), None, Formulation('0 + a + b')), product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'nesting_ids': np.random.RandomState(0).choice(['f', 'g'], id_data.size), 'clustering_ids': np.random.RandomState(0).choice(range(10), id_data.size) }, beta=[-5, 1, 1], gamma=[2, 1], rho=[0.1, 0.2], xi_variance=0.001, omega_variance=0.001, correlation=0.7, seed=0) simulation_results = simulation.solve() return simulation, simulation_results, []
def large_nested_logit_simulation() -> SimulationFixture: """Solve a simulation with ten markets, a linear constant, linear prices, a linear/cost characteristic, another two linear characteristics, another three cost characteristics, three nesting groups with the same nesting parameter, and a log-linear cost specification. """ id_data = build_id_data(T=10, J=20, F=9) simulation = Simulation( product_formulations=(Formulation('1 + prices + x + y + z'), None, Formulation('0 + log(x) + a + b + c')), product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'nesting_ids': np.random.RandomState(2).choice(['f', 'g', 'h'], id_data.size), 'clustering_ids': np.random.RandomState(2).choice(range(30), id_data.size) }, beta=[1, -6, 1, 2, 3], gamma=[0.1, 0.2, 0.3, 0.5], rho=0.1, xi_variance=0.00001, omega_variance=0.00001, correlation=0.9, costs_type='log', seed=2) simulation_results = simulation.solve() return simulation, simulation_results, []
def medium_blp_simulation() -> SimulationFixture: """Solve a simulation with four markets, linear/nonlinear/cost constants, two linear characteristics, two cost characteristics, a demographic interacted with second-degree prices, and an alternative ownership structure. """ id_data = build_id_data(T=4, J=25, F=6) simulation = Simulation( product_formulations=(Formulation('1 + x + y'), Formulation('1 + I(prices ** 2)'), Formulation('1 + a + b')), beta=[1, 2, 1], sigma=[ [0.5, 0], [0.0, 0], ], gamma=[1, 1, 2], product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'clustering_ids': np.random.RandomState(1).choice(range(20), id_data.size), 'ownership': build_ownership( id_data, lambda f, g: 1 if f == g else (0.1 if f > 3 and g > 3 else 0)) }, agent_formulation=Formulation('0 + f'), pi=[[+0], [-3]], integration=Integration('product', 4), xi_variance=0.0001, omega_variance=0.0001, correlation=0.8, seed=1) return simulation, simulation.solve()
def small_logit_simulation() -> SimulationFixture: """Solve a simulation with two markets, a linear constant, linear prices, a linear characteristic, a cost characteristic, and an acquisition. """ id_data = build_id_data(T=2, J=18, F=3, mergers=[{1: 0}]) simulation = Simulation( product_formulations=( Formulation('1 + prices + x'), None, Formulation('0 + a') ), beta=[1, -5, 1], sigma=None, gamma=2, product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'clustering_ids': np.random.RandomState(0).choice(range(10), id_data.size) }, xi_variance=0.001, omega_variance=0.001, correlation=0.7, seed=0 ) return simulation, simulation.solve()
def large_logit_simulation() -> SimulationFixture: """Solve a simulation with ten markets, a linear constant, linear prices, a linear/cost characteristic, another three cost characteristics, another two linear characteristics, an acquisition, a triple acquisition, and a log-linear cost specification. """ id_data = build_id_data(T=10, J=20, F=9, mergers=[{f: 4 + int(f > 0) for f in range(4)}]) simulation = Simulation( product_formulations=( Formulation('1 + prices + x + y + z'), None, Formulation('0 + log(x) + a + b + c') ), beta=[1, -6, 1, 2, 3], sigma=None, gamma=[0.1, 0.2, 0.3, 0.5], product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'clustering_ids': np.random.RandomState(2).choice(range(30), id_data.size) }, xi_variance=0.00001, omega_variance=0.00001, correlation=0.1, costs_type='log', seed=2 ) return simulation, simulation.solve()
def small_blp_simulation() -> SimulationFixture: """Solve a simulation with three markets, linear prices, a linear/nonlinear characteristic, two cost characteristics, and an acquisition. """ id_data = build_id_data(T=3, J=18, F=3, mergers=[{1: 0}]) simulation = Simulation( product_formulations=( Formulation('0 + prices + x'), Formulation('0 + x'), Formulation('0 + a + b') ), beta=[-5, 1], sigma=2, gamma=[2, 1], product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'clustering_ids': np.random.RandomState(0).choice(range(10), id_data.size) }, integration=Integration('product', 3), xi_variance=0.001, omega_variance=0.001, correlation=0.7, seed=0 ) return simulation, simulation.solve()
def medium_simulation(): """Solve a simulation with four markets, a nonlinear/cost constant, two linear characteristics, two cost characteristics, a demographic interacted with prices, a double acquisition, and a non-standard ownership structure. """ id_data = build_id_data(T=4, J=25, F=6, mergers=[{f: 2 for f in range(2)}]) simulation = Simulation( product_formulations=( Formulation('0 + x + y'), Formulation('1 + prices'), Formulation('1 + a + b') ), beta=[2, 1], sigma=[ [0.5, 0], [0, 0], ], gamma=[1, 1, 2], product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'ownership': build_ownership(id_data, lambda f, g: 1 if f == g else (0.1 if f > 3 and g > 3 else 0)) }, agent_formulation=Formulation('0 + f'), pi=[ [ 0], [-3] ], integration=Integration('product', 4), xi_variance=0.0001, omega_variance=0.0001, correlation=0.8, seed=1 ) return simulation, simulation.solve()
def test_merger(simulated_problem: SimulatedProblemFixture, ownership: bool, solve_options: Options) -> None: """Test that prices and shares simulated under changed firm IDs are reasonably close to prices and shares computed from the results of a solved problem. In particular, test that unchanged prices and shares are farther from their simulated counterparts than those computed by approximating a merger, which in turn are farther from their simulated counterparts than those computed by fully solving a merger. Also test that simple acquisitions increase HHI. These inequalities are only guaranteed because of the way in which the simulations are configured. Finally, test that we get the same results when we initialize a solve a simulation instead of using the convenient results methods. """ simulation, simulation_results, problem, _, results = simulated_problem # create changed ownership or firm IDs associated with a merger merger_ids = merger_ownership = None product_data = simulation_results.product_data if ownership: merger_ownership = build_ownership(product_data, lambda f, g: 1 if f == g or (f < 2 and g < 2) else 0) else: merger_ids = np.where(product_data.firm_ids < 2, 0, product_data.firm_ids) # get changed prices and shares changed_product_data = simulation.solve(merger_ids, merger_ownership).product_data # compute marginal costs and create a simulation with the results costs = results.compute_costs() results_simulation = Simulation( product_formulations=simulation.product_formulations[:2], product_data=simulation_results.product_data, beta=results.beta, sigma=results.sigma, pi=results.pi, rho=results.rho, agent_formulation=simulation.agent_formulation, agent_data=simulation.agent_data, xi=results.xi, costs=costs ) # solve for actual and approximate changed prices and shares estimated = results_simulation.solve(merger_ids, merger_ownership, problem.products.prices, **solve_options) estimated_prices = results.compute_prices(merger_ids, merger_ownership, costs, **solve_options) approximated_prices = results.compute_approximate_prices(merger_ids, merger_ownership, costs) estimated_shares = results.compute_shares(estimated_prices) approximated_shares = results.compute_shares(approximated_prices) # test that estimated prices are closer to changed prices than approximate prices approximated_prices_error = np.linalg.norm(changed_product_data.prices - approximated_prices) estimated_prices_error = np.linalg.norm(changed_product_data.prices - estimated_prices) np.testing.assert_array_less(estimated_prices_error, approximated_prices_error, verbose=True) # test that estimated shares are closer to changed shares than approximate shares approximated_shares_error = np.linalg.norm(changed_product_data.shares - approximated_shares) estimated_shares_error = np.linalg.norm(changed_product_data.shares - estimated_shares) np.testing.assert_array_less(estimated_shares_error, approximated_shares_error, verbose=True) # test that median HHI increases if not ownership: hhi = results.compute_hhi() changed_hhi = results.compute_hhi(merger_ids, estimated_shares) np.testing.assert_array_less(np.median(hhi), np.median(changed_hhi), verbose=True) # test that we get the same results from solving the simulation np.testing.assert_allclose(estimated_prices, estimated.product_data.prices, atol=1e-14, rtol=0, verbose=True) np.testing.assert_allclose(estimated_shares, estimated.product_data.shares, atol=1e-14, rtol=0, verbose=True)
def large_nested_blp_simulation() -> SimulationFixture: """Solve a simulation with 20 markets, varying numbers of products per market, a linear constant, linear/nonlinear prices, a linear/nonlinear/cost characteristic, another three linear characteristics, another two cost characteristics, demographics interacted with prices and the linear/nonlinear/cost characteristic, three nesting groups with the same nesting parameter, and a log-linear cost specification. """ id_data = build_id_data(T=20, J=20, F=9) keep = np.arange(id_data.size) np.random.RandomState(0).shuffle(keep) id_data = id_data[keep[:int(0.5 * id_data.size)]] simulation = Simulation( product_formulations=(Formulation('1 + prices + x + y + z + q'), Formulation('0 + prices + x'), Formulation('0 + log(x) + log(a) + log(b)')), product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'nesting_ids': np.random.RandomState(2).choice(['f', 'g', 'h'], id_data.size), 'clustering_ids': np.random.RandomState(2).choice(range(30), id_data.size) }, beta=[1, -10, 1, 2, 3, 1], sigma=[[1, 0], [0, 2]], pi=[[1, 0], [0, 2]], gamma=[0.1, 0.2, 0.3], rho=0.1, agent_formulation=Formulation('0 + f + g'), integration=Integration('product', 4), xi_variance=0.00001, omega_variance=0.00001, correlation=0.9, costs_type='log', seed=2) simulation_results = simulation.solve() simulated_micro_moments = [ ProductsAgentsCovarianceMoment(X2_index=0, demographics_index=0, value=0), ProductsAgentsCovarianceMoment(X2_index=1, demographics_index=1, value=0) ] return simulation, simulation_results, simulated_micro_moments
def large_blp_simulation() -> SimulationFixture: """Solve a simulation with 20 markets, varying numbers of products per market, a linear constant, linear/nonlinear prices, a linear/nonlinear/cost characteristic, another three linear characteristics, another two cost characteristics, demographics interacted with prices and the linear/nonlinear/cost characteristic, dense parameter matrices, a log-linear cost specification, and local differentiation instruments on the demand side. """ id_data = build_id_data(T=20, J=20, F=9) keep = np.arange(id_data.size) np.random.RandomState(0).shuffle(keep) id_data = id_data[keep[:int(0.5 * id_data.size)]] simulation = Simulation( product_formulations=(Formulation('1 + prices + x + y + z + q'), Formulation('0 + prices + x'), Formulation('0 + log(x) + log(a) + log(b)')), beta=[1, -10, 1, 2, 3, 1], sigma=[[1, -0.1], [0, +2.0]], gamma=[0.1, 0.2, 0.3], product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'clustering_ids': np.random.RandomState(2).choice(range(30), id_data.size) }, agent_formulation=Formulation('0 + f + g'), pi=[[1, 0], [0, 2]], integration=Integration('product', 4), xi_variance=0.00001, omega_variance=0.00001, correlation=0.9, costs_type='log', seed=2) simulation_results = simulation.solve() differentiation_instruments = np.c_[ build_differentiation_instruments(Formulation('0 + x + y + z + q'), simulation_results.product_data), build_matrix(Formulation('0 + a + b'), simulation_results.product_data )] simulation_results.product_data = update_matrices( simulation_results.product_data, { 'demand_instruments': (differentiation_instruments, simulation_results.product_data.demand_instruments.dtype) }) return simulation, simulation_results
def small_simulation(): """Solve a simulation with two markets, linear prices, a nonlinear characteristic, a cost characteristic, and an acquisition. """ simulation = Simulation( product_formulations=( Formulation('0 + prices'), Formulation('0 + x'), Formulation('0 + a') ), beta=-5, sigma=1, gamma=2, product_data=build_id_data(T=2, J=18, F=3, mergers=[{1: 0}]), integration=Integration('product', 3), xi_variance=0.001, omega_variance=0.001, correlation=0.7, seed=0 ) return simulation, simulation.solve()
def large_nested_blp_simulation() -> SimulationFixture: """Solve a simulation with ten markets, a linear constant, linear/nonlinear prices, a linear/nonlinear/cost characteristic, another three linear characteristics, another four cost characteristics, demographics interacted with prices and the linear/nonlinear/cost characteristic, three nesting groups with the same nesting parameter, an acquisition, a triple acquisition, and a log-linear cost specification. """ id_data = build_id_data(T=10, J=20, F=9, mergers=[{f: 4 + int(f > 0) for f in range(4)}]) simulation = Simulation( product_formulations=( Formulation('1 + prices + x + y + z + q'), Formulation('0 + prices + x'), Formulation('0 + log(x) + a + b + c + d') ), beta=[1, -10, 1, 2, 3, 1], sigma=[ [1, 0], [0, 2] ], gamma=[0.1, 0.2, 0.3, 0.1, 0.3], product_data={ 'market_ids': id_data.market_ids, 'firm_ids': id_data.firm_ids, 'nesting_ids': np.random.RandomState(2).choice(['f', 'g', 'h'], id_data.size), 'clustering_ids': np.random.RandomState(2).choice(range(30), id_data.size) }, agent_formulation=Formulation('0 + f + g'), pi=[ [1, 0], [0, 2] ], integration=Integration('product', 4), rho=0.05, xi_variance=0.00001, omega_variance=0.00001, correlation=0.9, costs_type='log', seed=2 ) return simulation, simulation.solve()