import pytest

import numpy as np
import eqtk


def test_promiscuous_binding_failure():
    A = np.array(
        [
            [
                1.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                1.0,
                0.0,
                0.0,
                1.0,
                1.0,
                1.0,
                1.0,
                0.0,
                0.0,
                0.0,
                0.0,
            ],
            [
                0.0,
                1.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                1.0,
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                1.0,
                1.0,
                1.0,
            ],
            [
                0.0,
                0.0,
                1.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
            ],
            [
                0.0,
                0.0,
                0.0,
                1.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
            ],
            [
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
                1.0,
                0.0,
                0.0,
                1.0,
                1.0,
                0.0,
                0.0,
            ],
            [
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                1.0,
                0.0,
                0.0,
                1.0,
                1.0,
                0.0,
                0.0,
                1.0,
                1.0,
            ],
        ]
    )
    G = np.array(
        [
            -0.51720535,
            -0.69471304,
            -1.78260496,
            -1.32337777,
            -0.63267947,
            -0.57923893,
            -0.78718634,
            -0.27521037,
            -0.13733511,
            -0.69433251,
            1.6858364,
            -0.43683479,
            0.39312096,
            -0.0625205,
            0.23139303,
            0.07680628,
            -0.52774543,
            1.74592678,
        ]
    )
    x0 = np.array(
        [
            [
                2.48257788e01,
                1.72132293e-01,
                1.14833731e-02,
                5.00547317e-02,
                1.38949549e-01,
                1.93069773e01,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
                0.00000000e00,
            ]
        ]
    )


def test_spontaneous_production_failure():
    N = np.array(
        [[1, 0, 1, 0, -1, 0], [1, 0, 0, 1, 0, -1], [1, 1, 1, 0, 0, 0]], dtype=float
    )

    A = np.array(
        [[0, 0, 0, 1, 0, 1], [1, 0, -1, 0, 0, 1], [0, -1, 1, 0, 1, 0]], dtype=float
    )

    G = np.array([0, 1, 2, 3, 4, 5])
    K = np.exp(-np.dot(N, G))

    for x0_val in [
        [1, 1, 1, 1, 1, 1],
        [0, 0, 0, 1, 0, 0],
        [1, 1, 1, 1, 0, 0],
        [0, 0, 0, 0, 0, 0],
    ]:
        x0 = np.array(x0_val, dtype=float)
        x_NK = eqtk.solve(c0=x0, N=N, K=K)

        with pytest.raises(ValueError) as excinfo:
            x_AG = eqtk.solve(c0=x0, A=A, G=G)
        excinfo.match("`A` must have all nonnegative entries.")

        assert eqtk.eqcheck(x_NK, x0, N=N, K=K)


def test_scale_factor_failure():
    A = np.array([[1.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0, 2.0]])
    G = np.array([0.0, 0.0, 0.77428976, -5.64873697, -0.95863043])
    x0 = np.array(
        [
            [
                5.50293892e-05,
                6.49273515e-08,
                2.75796219e-05,
                1.29854703e-07,
                3.24636758e-08,
            ]
        ]
    )
    x = eqtk.solve(c0=x0, A=A, G=G)
    assert eqtk.eqcheck(x, x0, A=A, G=G)


def test_trivial_elemental_failure():
    A = np.array([[1.0, 0.0], [0.0, 1.0]])
    G = np.array([0.0, 0.0])
    x0 = np.array([[3.48219906e-06, 1.32719868e-10]])
    assert np.allclose(eqtk.solve(c0=x0, A=A, G=G), x0)

    A = np.array([[1.0, 0.0], [0.0, 1.0]])
    G = np.array([0.0, 0.0])
    x0 = np.array([[2.24222410e-08, 1.63359284e-04]])
    assert np.allclose(eqtk.solve(c0=x0, A=A, G=G), x0)

    A = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
    G = np.array([0.0, 0.0, 0.0])
    x0 = np.array([[2.63761955e-04, 4.93360042e-07, 4.88340687e-07]])
    assert np.allclose(eqtk.solve(c0=x0, A=A, G=G), x0)


def test_past_failure_1():
    A = np.array([[1.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0, 2.0]])
    G = np.array([0.0, 0.0, -16.76857677, -2.38430181, 1.22028775])
    x0 = np.array(
        [
            [
                1.65989040e-10,
                1.07630096e-04,
                1.65989040e-10,
                1.65989040e-10,
                5.38150479e-05,
            ]
        ]
    )
    x = eqtk.solve(x0, A=A, G=G)
    assert eqtk.eqcheck(x, x0, A=A, G=G)


def test_past_failure_2():
    N = np.array([[-2.0, 1.0, 0.0, 0.0], [-3.0, 0.0, 1.0, 0.0], [-4.0, 0.0, 0.0, 1.0]])
    minus_log_K = np.array([-43.66660344, -68.14676841, -92.28023823])
    x0 = np.array([[1.87852623e-06, 3.75705246e-06, 1.25235082e-06, 4.69631557e-07]])
    K = np.exp(-minus_log_K)
    x = eqtk.solve(x0, N, K)
    assert eqtk.eqcheck(x, x0, N, K)


def test_small_conc_failure():
    A = np.array(
        [
            [1.0, 0.0, 1.0, 1.0, 0.0],
            [1.0, 1.0, 0.0, 0.0, 2.0],
            [1.0, 0.0, 0.0, 1.0, 2.0],
        ]
    )
    G = np.array(
        [
            -1.1323012373599138e02,
            -2.7028447814426110e-01,
            -2.3382656193096754e01,
            -1.0088531260804201e02,
            -5.7676558386243052e01,
        ]
    )
    x0 = np.array(
        [
            [
                1.8134373707286439e-08,
                3.5913242229740680e-14,
                3.5913242229740680e-14,
                3.5913242229740680e-14,
                1.7956621114870340e-14,
            ]
        ]
    )
    x = eqtk.solve(c0=x0, A=A, G=G)
    assert eqtk.eqcheck(x, x0, A=A, G=G)

[((96, 687), 'numpy.array', 'np.array', (['[[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0,\n    0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0,\n    0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,\n    0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0,\n    1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, \n    1.0], [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0,\n    0.0, 1.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,\n    1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0]]'], {}), '([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,\n    1.0, 0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,\n    1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 1.0, 0.0, 0.0,\n    0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0], [0.0,\n    0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, \n    1.0, 0.0, 1.0], [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0,\n    1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,\n    1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0]])\n', (104, 687), True, 'import numpy as np\n'), ((2582, 2833), 'numpy.array', 'np.array', (['[-0.51720535, -0.69471304, -1.78260496, -1.32337777, -0.63267947, -\n    0.57923893, -0.78718634, -0.27521037, -0.13733511, -0.69433251, \n    1.6858364, -0.43683479, 0.39312096, -0.0625205, 0.23139303, 0.07680628,\n    -0.52774543, 1.74592678]'], {}), '([-0.51720535, -0.69471304, -1.78260496, -1.32337777, -0.63267947, \n    -0.57923893, -0.78718634, -0.27521037, -0.13733511, -0.69433251, \n    1.6858364, -0.43683479, 0.39312096, -0.0625205, 0.23139303, 0.07680628,\n    -0.52774543, 1.74592678])\n', (2590, 2833), True, 'import numpy as np\n'), ((3070, 3224), 'numpy.array', 'np.array', (['[[24.8257788, 0.172132293, 0.0114833731, 0.0500547317, 0.138949549, \n    19.3069773, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]'], {}), '([[24.8257788, 0.172132293, 0.0114833731, 0.0500547317, 0.138949549,\n    19.3069773, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])\n', (3078, 3224), True, 'import numpy as np\n'), ((3749, 3838), 'numpy.array', 'np.array', (['[[1, 0, 1, 0, -1, 0], [1, 0, 0, 1, 0, -1], [1, 1, 1, 0, 0, 0]]'], {'dtype': 'float'}), '([[1, 0, 1, 0, -1, 0], [1, 0, 0, 1, 0, -1], [1, 1, 1, 0, 0, 0]],\n    dtype=float)\n', (3757, 3838), True, 'import numpy as np\n'), ((3858, 3947), 'numpy.array', 'np.array', (['[[0, 0, 0, 1, 0, 1], [1, 0, -1, 0, 0, 1], [0, -1, 1, 0, 1, 0]]'], {'dtype': 'float'}), '([[0, 0, 0, 1, 0, 1], [1, 0, -1, 0, 0, 1], [0, -1, 1, 0, 1, 0]],\n    dtype=float)\n', (3866, 3947), True, 'import numpy as np\n'), ((3967, 3995), 'numpy.array', 'np.array', (['[0, 1, 2, 3, 4, 5]'], {}), '([0, 1, 2, 3, 4, 5])\n', (3975, 3995), True, 'import numpy as np\n'), ((4507, 4571), 'numpy.array', 'np.array', (['[[1.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0, 2.0]]'], {}), '([[1.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0, 2.0]])\n', (4515, 4571), True, 'import numpy as np\n'), ((4580, 4638), 'numpy.array', 'np.array', (['[0.0, 0.0, 0.77428976, -5.64873697, -0.95863043]'], {}), '([0.0, 0.0, 0.77428976, -5.64873697, -0.95863043])\n', (4588, 4638), True, 'import numpy as np\n'), ((4648, 4745), 'numpy.array', 'np.array', (['[[5.50293892e-05, 6.49273515e-08, 2.75796219e-05, 1.29854703e-07, \n    3.24636758e-08]]'], {}), '([[5.50293892e-05, 6.49273515e-08, 2.75796219e-05, 1.29854703e-07, \n    3.24636758e-08]])\n', (4656, 4745), True, 'import numpy as np\n'), ((4880, 4907), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'A': 'A', 'G': 'G'}), '(c0=x0, A=A, G=G)\n', (4890, 4907), False, 'import eqtk\n'), ((4919, 4948), 'eqtk.eqcheck', 'eqtk.eqcheck', (['x', 'x0'], {'A': 'A', 'G': 'G'}), '(x, x0, A=A, G=G)\n', (4931, 4948), False, 'import eqtk\n'), ((4997, 5031), 'numpy.array', 'np.array', (['[[1.0, 0.0], [0.0, 1.0]]'], {}), '([[1.0, 0.0], [0.0, 1.0]])\n', (5005, 5031), True, 'import numpy as np\n'), ((5040, 5060), 'numpy.array', 'np.array', (['[0.0, 0.0]'], {}), '([0.0, 0.0])\n', (5048, 5060), True, 'import numpy as np\n'), ((5070, 5114), 'numpy.array', 'np.array', (['[[3.48219906e-06, 1.32719868e-10]]'], {}), '([[3.48219906e-06, 1.32719868e-10]])\n', (5078, 5114), True, 'import numpy as np\n'), ((5180, 5214), 'numpy.array', 'np.array', (['[[1.0, 0.0], [0.0, 1.0]]'], {}), '([[1.0, 0.0], [0.0, 1.0]])\n', (5188, 5214), True, 'import numpy as np\n'), ((5223, 5243), 'numpy.array', 'np.array', (['[0.0, 0.0]'], {}), '([0.0, 0.0])\n', (5231, 5243), True, 'import numpy as np\n'), ((5253, 5296), 'numpy.array', 'np.array', (['[[2.2422241e-08, 0.000163359284]]'], {}), '([[2.2422241e-08, 0.000163359284]])\n', (5261, 5296), True, 'import numpy as np\n'), ((5363, 5424), 'numpy.array', 'np.array', (['[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]'], {}), '([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])\n', (5371, 5424), True, 'import numpy as np\n'), ((5433, 5458), 'numpy.array', 'np.array', (['[0.0, 0.0, 0.0]'], {}), '([0.0, 0.0, 0.0])\n', (5441, 5458), True, 'import numpy as np\n'), ((5468, 5528), 'numpy.array', 'np.array', (['[[0.000263761955, 4.93360042e-07, 4.88340687e-07]]'], {}), '([[0.000263761955, 4.93360042e-07, 4.88340687e-07]])\n', (5476, 5528), True, 'import numpy as np\n'), ((5622, 5686), 'numpy.array', 'np.array', (['[[1.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0, 2.0]]'], {}), '([[1.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 0.0, 1.0, 2.0]])\n', (5630, 5686), True, 'import numpy as np\n'), ((5695, 5754), 'numpy.array', 'np.array', (['[0.0, 0.0, -16.76857677, -2.38430181, 1.22028775]'], {}), '([0.0, 0.0, -16.76857677, -2.38430181, 1.22028775])\n', (5703, 5754), True, 'import numpy as np\n'), ((5764, 5858), 'numpy.array', 'np.array', (['[[1.6598904e-10, 0.000107630096, 1.6598904e-10, 1.6598904e-10, 5.38150479e-05]]'], {}), '([[1.6598904e-10, 0.000107630096, 1.6598904e-10, 1.6598904e-10, \n    5.38150479e-05]])\n', (5772, 5858), True, 'import numpy as np\n'), ((5996, 6020), 'eqtk.solve', 'eqtk.solve', (['x0'], {'A': 'A', 'G': 'G'}), '(x0, A=A, G=G)\n', (6006, 6020), False, 'import eqtk\n'), ((6032, 6061), 'eqtk.eqcheck', 'eqtk.eqcheck', (['x', 'x0'], {'A': 'A', 'G': 'G'}), '(x, x0, A=A, G=G)\n', (6044, 6061), False, 'import eqtk\n'), ((6099, 6178), 'numpy.array', 'np.array', (['[[-2.0, 1.0, 0.0, 0.0], [-3.0, 0.0, 1.0, 0.0], [-4.0, 0.0, 0.0, 1.0]]'], {}), '([[-2.0, 1.0, 0.0, 0.0], [-3.0, 0.0, 1.0, 0.0], [-4.0, 0.0, 0.0, 1.0]])\n', (6107, 6178), True, 'import numpy as np\n'), ((6197, 6249), 'numpy.array', 'np.array', (['[-43.66660344, -68.14676841, -92.28023823]'], {}), '([-43.66660344, -68.14676841, -92.28023823])\n', (6205, 6249), True, 'import numpy as np\n'), ((6259, 6335), 'numpy.array', 'np.array', (['[[1.87852623e-06, 3.75705246e-06, 1.25235082e-06, 4.69631557e-07]]'], {}), '([[1.87852623e-06, 3.75705246e-06, 1.25235082e-06, 4.69631557e-07]])\n', (6267, 6335), True, 'import numpy as np\n'), ((6344, 6364), 'numpy.exp', 'np.exp', (['(-minus_log_K)'], {}), '(-minus_log_K)\n', (6350, 6364), True, 'import numpy as np\n'), ((6373, 6393), 'eqtk.solve', 'eqtk.solve', (['x0', 'N', 'K'], {}), '(x0, N, K)\n', (6383, 6393), False, 'import eqtk\n'), ((6405, 6430), 'eqtk.eqcheck', 'eqtk.eqcheck', (['x', 'x0', 'N', 'K'], {}), '(x, x0, N, K)\n', (6417, 6430), False, 'import eqtk\n'), ((6472, 6568), 'numpy.array', 'np.array', (['[[1.0, 0.0, 1.0, 1.0, 0.0], [1.0, 1.0, 0.0, 0.0, 2.0], [1.0, 0.0, 0.0, 1.0,\n    2.0]]'], {}), '([[1.0, 0.0, 1.0, 1.0, 0.0], [1.0, 1.0, 0.0, 0.0, 2.0], [1.0, 0.0, \n    0.0, 1.0, 2.0]])\n', (6480, 6568), True, 'import numpy as np\n'), ((6633, 6752), 'numpy.array', 'np.array', (['[-113.23012373599138, -0.2702844781442611, -23.382656193096754, -\n    100.88531260804201, -57.67655838624305]'], {}), '([-113.23012373599138, -0.2702844781442611, -23.382656193096754, -\n    100.88531260804201, -57.67655838624305])\n', (6641, 6752), True, 'import numpy as np\n'), ((6859, 6991), 'numpy.array', 'np.array', (['[[1.813437370728644e-08, 3.591324222974068e-14, 3.591324222974068e-14, \n    3.591324222974068e-14, 1.795662111487034e-14]]'], {}), '([[1.813437370728644e-08, 3.591324222974068e-14, \n    3.591324222974068e-14, 3.591324222974068e-14, 1.795662111487034e-14]])\n', (6867, 6991), True, 'import numpy as np\n'), ((7131, 7158), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'A': 'A', 'G': 'G'}), '(c0=x0, A=A, G=G)\n', (7141, 7158), False, 'import eqtk\n'), ((7170, 7199), 'eqtk.eqcheck', 'eqtk.eqcheck', (['x', 'x0'], {'A': 'A', 'G': 'G'}), '(x, x0, A=A, G=G)\n', (7182, 7199), False, 'import eqtk\n'), ((4179, 4208), 'numpy.array', 'np.array', (['x0_val'], {'dtype': 'float'}), '(x0_val, dtype=float)\n', (4187, 4208), True, 'import numpy as np\n'), ((4224, 4251), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'N': 'N', 'K': 'K'}), '(c0=x0, N=N, K=K)\n', (4234, 4251), False, 'import eqtk\n'), ((4431, 4463), 'eqtk.eqcheck', 'eqtk.eqcheck', (['x_NK', 'x0'], {'N': 'N', 'K': 'K'}), '(x_NK, x0, N=N, K=K)\n', (4443, 4463), False, 'import eqtk\n'), ((5138, 5165), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'A': 'A', 'G': 'G'}), '(c0=x0, A=A, G=G)\n', (5148, 5165), False, 'import eqtk\n'), ((5321, 5348), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'A': 'A', 'G': 'G'}), '(c0=x0, A=A, G=G)\n', (5331, 5348), False, 'import eqtk\n'), ((5552, 5579), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'A': 'A', 'G': 'G'}), '(c0=x0, A=A, G=G)\n', (5562, 5579), False, 'import eqtk\n'), ((4012, 4024), 'numpy.dot', 'np.dot', (['N', 'G'], {}), '(N, G)\n', (4018, 4024), True, 'import numpy as np\n'), ((4266, 4291), 'pytest.raises', 'pytest.raises', (['ValueError'], {}), '(ValueError)\n', (4279, 4291), False, 'import pytest\n'), ((4323, 4350), 'eqtk.solve', 'eqtk.solve', ([], {'c0': 'x0', 'A': 'A', 'G': 'G'}), '(c0=x0, A=A, G=G)\n', (4333, 4350), False, 'import eqtk\n')]