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)

[((8, 8, 131, 5), 'numpy.array', 'np.array', ({(9, 8, 130, 9): '[[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]])', True, 'import numpy as np\n'), ((132, 8, 153, 5), 'numpy.array', 'np.array', ({(133, 8, 152, 9): '[-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])', True, 'import numpy as np\n'), ((154, 9, 177, 5), 'numpy.array', 'np.array', ({(155, 8, 176, 9): '[[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]])', True, 'import numpy as np\n'), ((181, 8, 183, 5), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((185, 8, 187, 5), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((189, 8, 189, 36), 'numpy.array', 'np.array', ({(189, 17, 189, 35): '[0, 1, 2, 3, 4, 5]'}, {}), '([0, 1, 2, 3, 4, 5])', True, 'import numpy as np\n'), ((209, 8, 209, 72), 'numpy.array', 'np.array', ({(209, 17, 209, 71): '[[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]])', True, 'import numpy as np\n'), ((210, 8, 210, 66), 'numpy.array', 'np.array', ({(210, 17, 210, 65): '[0.0, 0.0, 0.77428976, -5.64873697, -0.95863043]'}, {}), '([0.0, 0.0, 0.77428976, -5.64873697, -0.95863043])', True, 'import numpy as np\n'), ((211, 9, 221, 5), 'numpy.array', 'np.array', ({(212, 8, 220, 9): '[[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]])', True, 'import numpy as np\n'), ((222, 8, 222, 35), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((223, 11, 223, 40), 'eqtk.eqcheck', 'eqtk.eqcheck', (), '', False, 'import eqtk\n'), ((227, 8, 227, 42), 'numpy.array', 'np.array', ({(227, 17, 227, 41): '[[1.0, 0.0], [0.0, 1.0]]'}, {}), '([[1.0, 0.0], [0.0, 1.0]])', True, 'import numpy as np\n'), ((228, 8, 228, 28), 'numpy.array', 'np.array', ({(228, 17, 228, 27): '[0.0, 0.0]'}, {}), '([0.0, 0.0])', True, 'import numpy as np\n'), ((229, 9, 229, 53), 'numpy.array', 'np.array', ({(229, 18, 229, 52): '[[3.48219906e-06, 1.32719868e-10]]'}, {}), '([[3.48219906e-06, 1.32719868e-10]])', True, 'import numpy as np\n'), ((232, 8, 232, 42), 'numpy.array', 'np.array', ({(232, 17, 232, 41): '[[1.0, 0.0], [0.0, 1.0]]'}, {}), '([[1.0, 0.0], [0.0, 1.0]])', True, 'import numpy as np\n'), ((233, 8, 233, 28), 'numpy.array', 'np.array', ({(233, 17, 233, 27): '[0.0, 0.0]'}, {}), '([0.0, 0.0])', True, 'import numpy as np\n'), ((234, 9, 234, 53), 'numpy.array', 'np.array', ({(234, 18, 234, 52): '[[2.2422241e-08, 0.000163359284]]'}, {}), '([[2.2422241e-08, 0.000163359284]])', True, 'import numpy as np\n'), ((237, 8, 237, 69), 'numpy.array', 'np.array', ({(237, 17, 237, 68): '[[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]])', True, 'import numpy as np\n'), ((238, 8, 238, 33), 'numpy.array', 'np.array', ({(238, 17, 238, 32): '[0.0, 0.0, 0.0]'}, {}), '([0.0, 0.0, 0.0])', True, 'import numpy as np\n'), ((239, 9, 239, 69), 'numpy.array', 'np.array', ({(239, 18, 239, 68): '[[0.000263761955, 4.93360042e-07, 4.88340687e-07]]'}, {}), '([[0.000263761955, 4.93360042e-07, 4.88340687e-07]])', True, 'import numpy as np\n'), ((244, 8, 244, 72), 'numpy.array', 'np.array', ({(244, 17, 244, 71): '[[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]])', True, 'import numpy as np\n'), ((245, 8, 245, 67), 'numpy.array', 'np.array', ({(245, 17, 245, 66): '[0.0, 0.0, -16.76857677, -2.38430181, 1.22028775]'}, {}), '([0.0, 0.0, -16.76857677, -2.38430181, 1.22028775])', True, 'import numpy as np\n'), ((246, 9, 256, 5), 'numpy.array', 'np.array', ({(247, 8, 255, 9): '[[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]])', True, 'import numpy as np\n'), ((257, 8, 257, 32), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((258, 11, 258, 40), 'eqtk.eqcheck', 'eqtk.eqcheck', (), '', False, 'import eqtk\n'), ((262, 8, 262, 87), 'numpy.array', 'np.array', ({(262, 17, 262, 86): '[[-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]])', True, 'import numpy as np\n'), ((263, 18, 263, 70), 'numpy.array', 'np.array', ({(263, 27, 263, 69): '[-43.66660344, -68.14676841, -92.28023823]'}, {}), '([-43.66660344, -68.14676841, -92.28023823])', True, 'import numpy as np\n'), ((264, 9, 264, 85), 'numpy.array', 'np.array', ({(264, 18, 264, 84): '[[1.87852623e-06, 3.75705246e-06, 1.25235082e-06, 4.69631557e-07]]'}, {}), '([[1.87852623e-06, 3.75705246e-06, 1.25235082e-06, 4.69631557e-07]])', True, 'import numpy as np\n'), ((265, 8, 265, 28), 'numpy.exp', 'np.exp', ({(265, 15, 265, 27): '-minus_log_K'}, {}), '(-minus_log_K)', True, 'import numpy as np\n'), ((266, 8, 266, 28), 'eqtk.solve', 'eqtk.solve', ({(266, 19, 266, 21): 'x0', (266, 23, 266, 24): 'N', (266, 26, 266, 27): 'K'}, {}), '(x0, N, K)', False, 'import eqtk\n'), ((267, 11, 267, 36), 'eqtk.eqcheck', 'eqtk.eqcheck', ({(267, 24, 267, 25): 'x', (267, 27, 267, 29): 'x0', (267, 31, 267, 32): 'N', (267, 34, 267, 35): 'K'}, {}), '(x, x0, N, K)', False, 'import eqtk\n'), ((271, 8, 277, 5), 'numpy.array', 'np.array', ({(272, 8, 276, 9): '[[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]])', True, 'import numpy as np\n'), ((278, 8, 286, 5), 'numpy.array', 'np.array', ({(279, 8, 285, 9): '[-113.23012373599138, -0.2702844781442611, -23.382656193096754, -\n    100.88531260804201, -57.67655838624305]'}, {}), '([-113.23012373599138, -0.2702844781442611, -23.382656193096754, -\n    100.88531260804201, -57.67655838624305])', True, 'import numpy as np\n'), ((287, 9, 297, 5), 'numpy.array', 'np.array', ({(288, 8, 296, 9): '[[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]])', True, 'import numpy as np\n'), ((298, 8, 298, 35), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((299, 11, 299, 40), 'eqtk.eqcheck', 'eqtk.eqcheck', (), '', False, 'import eqtk\n'), ((198, 13, 198, 42), 'numpy.array', 'np.array', (), '', True, 'import numpy as np\n'), ((199, 15, 199, 42), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((205, 15, 205, 47), 'eqtk.eqcheck', 'eqtk.eqcheck', (), '', False, 'import eqtk\n'), ((230, 23, 230, 50), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((235, 23, 235, 50), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((240, 23, 240, 50), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n'), ((190, 16, 190, 28), 'numpy.dot', 'np.dot', ({(190, 23, 190, 24): 'N', (190, 26, 190, 27): 'G'}, {}), '(N, G)', True, 'import numpy as np\n'), ((201, 13, 201, 38), 'pytest.raises', 'pytest.raises', ({(201, 27, 201, 37): 'ValueError'}, {}), '(ValueError)', False, 'import pytest\n'), ((202, 19, 202, 46), 'eqtk.solve', 'eqtk.solve', (), '', False, 'import eqtk\n')]