pacti-org / pacti

A package for compositional system analysis and design
https://www.pacti.org
BSD 3-Clause "New" or "Revised" License
19 stars 5 forks source link

[BUG] IndexError: too many indices for array: array is 0-dimensional, but 1 were indexed #320

Open NicolasRouquette opened 1 year ago

NicolasRouquette commented 1 year ago

Describe the bug A clear and concise description of what the bug is.

Plotting constraints can produce a strange error.

To Reproduce Steps to reproduce the behavior:

from pacti.terms.polyhedra import PolyhedralContract, PolyhedralTermList
from pacti.terms.polyhedra.plots import _get_bounding_vertices

c = PolyhedralContract.from_string(
    input_vars=["t_var"],
    output_vars=["d_var"],
    assumptions=[],
    guarantees=[
        "d_var + 4 t_var <= 40",
        "-d_var - 5 t_var <= -40"
    ]
)

print(c)

ptl = c.g

# from plots._plot_constraints
res_tuple = PolyhedralTermList.termlist_to_polytope(ptl, PolyhedralTermList([]))

a_mat = res_tuple[1]
b = res_tuple[2]

x, y = _get_bounding_vertices(a_mat, b)

Expected behavior A clear and concise description of what you expected to happen.

No error

Screenshots If applicable, add screenshots to help explain your problem.

System (please complete the following information):

Additional context Add any other context about the problem here.

(pacti-mexec-tasks-3.9) nfr@nfr-desktop:/opt/local/github.autonomica/pacti-mexec-tasks$ /opt/local/github.autonomica/pacti-mexec-tasks/.venv/bin/python /opt/local/github.autonomica/pacti-mexec-tasks/src/pacti_mexec_tasks/test1.py
InVars: [t_var]
OutVars:[d_var]
A: [

]
G: [
  d_var + 4 t_var <= 40
  -d_var - 5 t_var <= -40
]
Traceback (most recent call last):
  File "/opt/local/github.autonomica/pacti-mexec-tasks/src/pacti_mexec_tasks/test1.py", line 24, in <module>
    x, y = _get_bounding_vertices(a_mat, b)
  File "/opt/local/github.autonomica/pacti-mexec-tasks/.venv/lib/python3.9/site-packages/pacti/terms/polyhedra/plots.py", line 133, in _get_bounding_vertices
    interior_point = _get_feasible_point(a_mat, b)
  File "/opt/local/github.autonomica/pacti-mexec-tasks/.venv/lib/python3.9/site-packages/pacti/terms/polyhedra/plots.py", line 127, in _get_feasible_point
    return np.array(res["x"])[0:-1]  # noqa: WPS349 Found redundant subscript slice
IndexError: too many indices for array: array is 0-dimensional, but 1 were indexed
(pacti-mexec-tasks-3.9) nfr@nfr-desktop:/opt/local/github.autonomica/pacti-mexec-tasks$ 
NicolasRouquette commented 1 year ago

The problem is in this function in pacti.terms.polyhedra.plots:

def _get_feasible_point(a_mat: np.ndarray, b: np.ndarray, interior: bool = True) -> np.ndarray:
    a_mat_1 = np.concatenate((a_mat, np.linalg.norm(a_mat, axis=1, keepdims=True)), axis=1)
    a_mat_new = np.concatenate((a_mat_1, np.array([[0, 0, -1]])), axis=0)
    b_new = np.concatenate((np.reshape(b, (-1, 1)), np.array([[0]])), axis=0)
    obj = np.array([0, 0, 1])
    if interior:
        obj = np.array([0, 0, -1])
    res = linprog(c=obj, A_ub=a_mat_new, b_ub=b_new, bounds=(None, None))
    if res["status"] == 2:
        raise ValueError("Constraints are unfeasible")
    return np.array(res["x"])[0:-1]  # noqa: WPS349 Found redundant subscript slice

The logic lacks a check for res["status"] == 3 (unbounded variables).

iincer commented 1 year ago

From what I recall, the function plot_guarantees should never find unbounded behavior. This is because the bounds provided by the user are used as additional constraints in the optimization. Why are you calling _get_bounding_vertices directly?