def test_weights_and_formatting(dimensions: int, specification: str,
                                size: int) -> None:
    """Test that weights sum to one and that the configurations can be formatted."""
    integration = Integration(specification, size)
    assert str(integration)
    weights = integration._build(dimensions)[1]
    np.testing.assert_allclose(weights.sum(), 1, rtol=0, atol=1e-12)
Exemple #2
0
def test_hermite_integral(dimensions, specification, size, naive_specification):
    """Test if approximations of a simple Gauss-Hermite integral (product of squared variables of integration with
    respect to the standard normal density) are reasonably correct. Then, if a naive specification is given, tests that
    it performs worse, even with an order of magnitude more nodes.
    """
    integral = lambda n, w: w.T @ (n ** 2).prod(axis=1)
    nodes, weights = Integration(specification, size, seed=0)._build(dimensions)
    simulated = integral(nodes, weights)
    np.testing.assert_allclose(simulated, 1, rtol=0, atol=0.01)
    if naive_specification:
        naive = integral(*Integration(naive_specification, 10 * weights.size, seed=0)._build(dimensions))
        np.testing.assert_array_less(np.linalg.norm(simulated - 1), np.linalg.norm(naive - 1))
def test_nwspgr(dimensions: int, level: int, nested: bool) -> None:
    """Compare with output from the Matlab function nwspgr by Florian Heiss and Viktor Winschel."""
    if shutil.which('matlab') is None:
        return pytest.skip(
            "Failed to find a MATLAB executable in this environment.")
    with tempfile.NamedTemporaryFile() as handle:
        command = ';'.join([
            f"[nodes, weights] = nwspgr('{'KPN' if nested else 'GQN'}', {dimensions}, {level})",
            f"save('{handle.name}', 'nodes', 'weights')", 'exit'
        ])
        subprocess.run([
            'matlab', '-nodesktop', '-nosplash', '-minimize', '-wait', '-r',
            f'"{command}"'
        ])
        nwspgr = scipy.io.loadmat(handle.name)
    nodes, weights = Integration('nested_grid' if nested else 'grid',
                                 level)._build(dimensions)
    np.testing.assert_allclose(nwspgr['nodes'],
                               np.c_[nodes],
                               rtol=0,
                               atol=1e-14)
    np.testing.assert_allclose(nwspgr['weights'],
                               np.c_[weights],
                               rtol=0,
                               atol=1e-14)
Exemple #4
0
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()
Exemple #5
0
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()
Exemple #6
0
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()
Exemple #7
0
def large_nested_blp_simulation() -> SimulationFixture:
    """Solve a simulation with 20 markets, varying numbers of products per market, a linear constant, log-normal
    coefficients on 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 + x + y + z + q'),
            Formulation('0 + I(-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, 1, 2, 3, 1],
        sigma=[
            [0.5, 0],
            [0.0, 2]
        ],
        pi=[
            [2, 1, 0],
            [0, 0, 2]
        ],
        gamma=[0.1, 0.2, 0.3],
        rho=0.1,
        agent_formulation=Formulation('1 + f + g'),
        integration=Integration('product', 4),
        xi_variance=0.00001,
        omega_variance=0.00001,
        correlation=0.9,
        distributions=['lognormal', 'normal'],
        costs_type='log',
        seed=2,
    )
    simulation_results = simulation.replace_endogenous()
    simulated_micro_moments = [DemographicExpectationMoment(
        product_id=None, demographics_index=1, value=0, market_ids=simulation.unique_market_ids[3:5]
    )]
    return simulation, simulation_results, {}, simulated_micro_moments
Exemple #8
0
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
Exemple #9
0
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()
Exemple #10
0
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()