shortwavedave / CS6380_A4

0 stars 0 forks source link

CS4300_Ask.m Cannot Find watchlist Python Module. #1

Closed imaspacepirate closed 4 years ago

imaspacepirate commented 4 years ago

Summary:

The following sequence of commands lead to an error:

>> addpath('tchlib/', 'solvers/');

>> KB(1).clauses = [1];
>> KB(2).clauses = [-1 2];
>> thm(1).clause = [2];

>> CS4300_Ask(KB, thm)
Traceback (most recent call last):
  File "sat.py", line 18, in <module>                                                                        
    from solvers import recursive_sat                 
  File "./solvers/recursive_sat.py", line 6, in <module>
    from watchlist import 
ModuleNotFoundError: No module named 'watchlist'

What To Do:

imaspacepirate commented 4 years ago

Problem

In Python, when importing a module named foo, the interpreter first searches for a built-in module with that name. If the module foo is not found, the interpreter then searchers for a file named foo.py in a list of directories given by the variable sys.path which is initialized from the following location:

Our project has the following structure:

CS6380_A4/ 
├── A bunch of Matlab `.m` files
├── A bunch of `.pyc` files and __pycache__ directory.
├── `satinstance.py`
├── `sat.py`
├── solvers/
│   ├── __init__.py
│   ├── iterative_sat.py
│   ├── recursive_sat.py
│   ├── watchlist.py
│   └── A bunch of `.pyc` files and __pycache__ directory.
└── tchlib/ 

When we call CS4300_Ask it executes https://github.com/shortwavedave/CS6380_A4/blob/15a63743c3a0dd7cd2869feb67c242a393d108d2/CS4300_Ask.m#L33-L38 and depending on the operating system, the appropriate call to sat.py is made. This means that sat.py is the main entry point for the Python interpreter. Since sat.py executes https://github.com/shortwavedave/CS6380_A4/blob/15a63743c3a0dd7cd2869feb67c242a393d108d2/sat.py#L16-L19 then as the modules above are not built-in, sat.py does not modify PYTHONPATH in any way, and the installation-dependent default path does not point to the location of these modules, it follows that the interpreter will search the current directory that contains sat.py for these modules.

Now, why does this matter? Python allows you to import modules using absolute or relative paths. In both cases, the paths are in relation to the directory where the script is being executed (in our case, within CS6380_A4/). Depending on the version of Python, the __init__.py file may or may not be needed to let the interpreter know that it should treat directories containing files as packages. All of the Python code in the project was written for Python 2.7 which respected the __init__.py behavior such that the statements in solvers/iterative_sat.py and solvers/recursive_sat.py respectively would work, https://github.com/shortwavedave/CS6380_A4/blob/720e9d58dd777d2eb33fe419ab5b33b8820486c0/solvers/iterative_sat.py#L6 https://github.com/shortwavedave/CS6380_A4/blob/720e9d58dd777d2eb33fe419ab5b33b8820486c0/solvers/recursive_sat.py#L6

However, in Python 3.0 and later, this is not the case, so the previous statements fail.

Solution

The requires us to change the relative paths in solvers/iterative_sat.py and solvers/recursive_sat.py to absolute paths, https://github.com/shortwavedave/CS6380_A4/blob/15a63743c3a0dd7cd2869feb67c242a393d108d2/solvers/iterative_sat.py#L6 https://github.com/shortwavedave/CS6380_A4/blob/15a63743c3a0dd7cd2869feb67c242a393d108d2/solvers/recursive_sat.py#L6

This solution is robust as it works for all versions of python irrespective of the operating system.

Verification

Executing tests 1 and 2 in Matlab should produce the output shown below.

Test 1

eqn1

In Matlab:

>> KB(1).clauses = [1];
>> KB(2).clauses = [-1 2];
>> thm(1).clauses = [-2];
>> CS4300_Ask(KB, thm)

ans =

     0

>>

Test 2

eqn2

In Matlab:

>> KB(1).clauses = [1];
>> KB(2).clauses = [-1];
>> thm(1).clauses = [3];
>> CS4300_Ask(KB, thm)

ans =

     1

>>