Nupic.Core C# Bindings

I have managed to get the CMake to load up in Visual Studio 2017 and it tries to compile but some of the third party packages are breaking. For example the Yaml-cpp sub cmake is creating a library that has a slightly different name than expected and it breaks the build. About half of the 30 or so packages are breaking so there is some work to do.

Here is what I have so far as a procedure to build under Visual Studio 2017.

  1. Install the prerequisites:
    Visual Studio 2017 from Download Visual Studio Tools - Install Free for Windows, Mac, Linux (Community version is free)
    This has the Visual C++ 14.0 compiler.

    CMake install from https://cmake.org/

    GIT install from Git - Downloads
    Includes patch.exe required when building external libraries using Visual Studio.
    Make sure C:\Program Files\Git\usr\bin is added to your PATH environment variable
    and restart your Command Prompt window if you have one open.

    Python Download and install Python 3.6.x (64bit version) from Python.org.
    Be sure to click the checkbox to have it set the environment variables.
    If you already have Python 2.7.x installed it is ok. This will place
    the python path environment variable for Python 3.6 ahead of those for
    Python 2.7 so that typing “python” will get Python 3.6.

        Opened a Command Prompt window and verified that it has the right python version.
    
            C:> python
            Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
             on win32
            Type "help", "copyright", "credits" or "license" for more information.
            >>> 
        Type ctl-Z CR to exit python.
    

    pip This is installed with Python but you need to update it to make sure it is the latest.
    C:> python -m pip install -U pip

    Python support modules
    Start Command Prompt “as Administrator”
    C:> pip install -U cython
    C:> pip install -U setuptools
    C:> pip install wheel
    C:> pip install --user numpy
    It should get the latest version of numpy (numpy-1.13.3-cp36-none-win_amd64.whl)

  2. Clone nupic.core repository
    C:> cd \xxx (or where you want the repository to be)
    C:\xxx> git clone GitHub - numenta/nupic.core-legacy: Implementation of core NuPIC algorithms in C++ (under construction)

  3. Use CMake to create the Visual Studio solution and project files
    C:\xxx> cd nupic.core
    C:\xxx\nupic.core> set NUPIC_CORE=%CD%
    C:\xxx\nupic.core> mkdir build\scripts
    C:\xxx\nupic.core> cd build\scripts

    Run cmake to generate MSVC 2017 solution and project files
    C:\xxx\nupic.core\build\scripts> cmake -G “Visual Studio 15 2017 Win64”
    -DCMAKE_INSTALL_PREFIX=…\release
    -DPY_EXTENSIONS_DIR=…..\bindings\py\src\nupic\bindings
    …..

  4. Start up Visual Studio
    C:\xxx\nupic.core\build\scripts> nupic_core_main.sln
    Make sure to select the Release x64 configuration then build the ALL_BUILD project.

Once we get this running there are some install steps to get things in the right places. Then we have to create the bindings for Python, C#, and whatever else.

I think I’m at that point. Crash course in C++, Python, CMake, and building in multiple environments.
Had to install GnuWin32 for patch.exe.

7 succeeded, and then starts to fail at yaml-cpp-bundle.

Going to start the prototype. I’ll share it when I get it up. I just need to learn all this bit by bit without all of nupic.

@heilerm I made some progress today. I still have 12 out of 29 projects that are failing. Almost all of them have to do with the Python interface.

Again, what I am trying to do is get the existing Nupic.core codebase compiling on Visual Studio 2017 with Python 3. Once that is working we can look at ways to extract the Python bindings into a separate build and then add the C# bindings in the same way.

So here are some changes you can make. Like I said, this does not all work yet.

+++++++++++++++++
When building under Visual Studio, the yaml-cpp library is built with a slightly different name.
Generated file is F:\AI\community\nupic.core\build\scripts\ThirdParty\Build\YamlCppStaticLib\Release\libyaml-cppmd.lib

nupic.core/extrnal/YamlCppLib.cmake line #44
Change

# Path to static yaml-cpp installed by external project
set(yamlcpplib_built_archive_file
    "${yamlcpplib_install_lib_dir}/${STATIC_PRE}yaml-cpp${STATIC_SUF}")

to

# Path to static yaml-cpp installed by external project
if(MSVC)
    set(yamlcpplib_built_archive_file
        "${yamlcpplib_install_lib_dir}/lib${STATIC_PRE}yaml-cppmd${STATIC_SUF}")
else()
    set(yamlcpplib_built_archive_file
        "${yamlcpplib_install_lib_dir}/${STATIC_PRE}yaml-cpp${STATIC_SUF}")
endif()

+++++++++++++++++
7> LINK : fatal error LNK1181: cannot open input file ‘F:/AI/community/nupic.core/build/scripts/ThirdParty/Build/YamlStaticLib/yaml.lib’
Generated library file is at ‘F:/AI/community/nupic.core/build/scripts/ThirdParty/Build/YamlStaticLib/Release/yaml.lib’

nupic.core/external/YamlLib.cmake line #38
change

# NOTE Yaml lib doesn't have an install target and leaves artifacts in build dir
set(yamllib_build_dir "${EP_BASE}/Build/YamlStaticLib")

to

# NOTE Yaml lib doesn't have an install target and leaves artifacts in build dir
if(MSVC)
    set(yamllib_build_dir "${EP_BASE}/Build/YamlStaticLib/Release")
else()
    set(yamllib_build_dir "${EP_BASE}/Build/YamlStaticLib")
endif()

+++++++++++++++++
9> c1xx : fatal error C1083: Cannot open source file: ‘Files/Python36/Lib/site-packages/numpy/core/include’: No such file or directory
This path should be C:/Program Files/Python36/Lib/site-packages/numpy/core/include
There is a problem with the space in filename: “Program Files”.

nupic.core/src/CMakeLists.txt Line#189
change

#
# Locate Python artifacts
#
find_package(PythonLibs REQUIRED)
include_directories(SYSTEM ${PYTHON_INCLUDE_DIRS})

to

#
# Locate Python artifacts
#
find_package(PythonLibs ${PYTHON_VERSION_STRING} REQUIRED)
include_directories(SYSTEM ${PYTHON_INCLUDE_DIRS})

nupic.core/src/CMakeLists.txt Line#129
change
#

# Find Python Interp, min. v2.7
# And NumPy core directory
#
find_package(PythonInterp 2.7 REQUIRED)
message(STATUS "CMAKE Found python interpreter ${PYTHON_EXECUTABLE} version=${PYTHON_VERSION_STRING}")

to

#
# Find Python Interp, min. v3.x
# And NumPy core directory
#
# There was a bug in CMake before Version 3.0 where find_package returned the wrong python parameters.
cmake_minimum_required(VERSION 3.0)
find_package(PythonInterp 3 REQUIRED)
message(STATUS "CMAKE Found python interpreter ${PYTHON_EXECUTABLE} version=${PYTHON_VERSION_STRING}")

Agreed. I’d like to add bindings without updating dependencies, but it seems to have proven difficult, working in VS 2017. Mind as well update, as long as we’re doing community branches, especially if our target is C# and VS 2017.

Do you have this in a community fork?

As for my sandbox\prototype… I got distracted with updating CMake to produce a bit better project structure in VS 2017. A couple things I couldn’t figure out with master:

  • Header files aren’t showing up in VS 2017.
  • Header files aren’t in an include folder - they’re in ~/src.
  • No filters are configured for the subfolders (algorithms, etc.) - it’s a little hard to navigate in the IDE without them.

I should have that on GitHub soon, then I’ll add Swig. Looks like the interface files can’t be generated, but they are in ~/src/nupic/bindings. Each subfolder has its own interface. Hoping that can be broken into smaller files - it should be easier to manage as more bindings are added\updated\deleted. Again, just starting small so I can get a hang of all this. I’m not of much help right now.

You have a few options. I would prefer if community forks were in HTM Community · GitHub along with other HTM-related community projects. Either of you can start with your own fork(s) and I can move them here when you’re ready. I’ll just want to make sure that it is clear in the README that it is a community fork.

Ah… that wasn’t clear. Not sure how I missed that. That makes sense.

Ok. I will continue on my local sandbox until I have a clean build. Then we can put it up into the community fork. I would rather not publish something that does not work :slight_smile:

@heilerm I am finding that some of the C++ modules use Python data structures (particularly numpy arrays). That will not be very useful for C#. So, we cannot just ignore the binding modules and build the rest. It is more complicated than that.

Aren’t those interfaced in ~/src/nupic/py_spport? Still don’t have a comprehensive understanding of what’s going on at that end.

Well, most of the python interface goes through py_support. I think I can tell what is going on a little easier if I first get a running program so I can use the debugger.

I finally got nupic_core_solo to compile and I have nupic_core.lib.

9> All outputs are up-to-date.
9> nupic_core_solo.vcxproj → F:\AI\community\nupic.core\build\scripts\src\Release\nupic_core_solo.lib

However in the nupic_core target it tries to combine all of the libraries using merge_static_libraries() which is in NupicLibraryUtils.cmake. It fails with

9> LINK : fatal error LNK1104: cannot open file ‘$<TARGET_FILE:nupic_core_solo>’
9>Done building target “Lib” in project “nupic_core.vcxproj” – FAILED.

I look at the target location for nupic_core_solo (nupic.core\build\scripts\src\Release\nupic_core_solo.lib) and the file is there. So the path prefix it is working with in the nupic_core project might be wrong. Cannot quite put my finger on the problem yet.

I did notice there was some sort of warning when it ran merge_static_libraries(). I don’t know what it means:

1> – MERGE_STATIC_LIBRARIES LIB_TARGET=nupic_core, STATIC_LIBS = nupic_core_solo;capnp-bundle;yaml-cpp-bundle;yaml-bundle;apr-1-bundle;aprutil-1-bundle;z-bundle
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib nupic_core_solo.
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib capnp-bundle.
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib yaml-cpp-bundle.
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib yaml-bundle.
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib apr-1-bundle.
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib aprutil-1-bundle.
1> – MERGE_STATIC_LIBRARIES: Link interface not specified in source lib z-bundle.

Any ideas?

correction. I have nupic_core_solo.lib. It is nupic_core.lib that I am trying to create by merging all of the static libraries and is failing.

This looks highly suspect.

Hard to tell, though. Still learning from the bottom up.

Matt, here is a link to a page describing CMake syntax that might be useful.
https://cmake.org/Wiki/CMake/Language_Syntax

I did get the nupic_core.lib created but it does not contain all of the external libraries. I think there is a problem with the CMake scripts that pass the list of libraries to the linker. Still working on it.

Ok, I have a Community Fork of nupic.core that builds under Visual Studio 2017 and uses (actually requires) Python 3.x. The project builds and passes all of the unit tests.

I tried not to make any change that would prevent Linux users from also building from the same CMake files but I have not verified that it still works. I have not tried to run any of the Python examples but they should run if they are ported from Python 2.7 to Python 3.x.

I created a README.md that explains how to use it and that is part of the package.

So, now what should I do with it?

I think it should be placed in the htm-community github, but what name should we use so it is not confused with the numenta production release? Keep in mind that the next thing we will take on is split out the Python interface (with all of the Python-support and Swig components) into a separate build so that the C++ core is independent of calling programming language. Then we can build a parallel C# language interface in its own build. So with that in mind, do we still call it nupic.core?

While you are thinking about what to call it, I put my fork up on my github account so you can look at it.

Nice! Gonna set that up this weekend. Not sure what to call it. Maybe nupic.core is just find under the htm-community?

While going though the nupic.core code and specs trying to decide what to include in the Community Branch, I noticed that much of the complexity of the build has to do with serialization. I assume that serialization is ONLY used to save a session to disk and to restore a session from disk…not for language interface. Is this correct?

There are two types of serialization implemented in nupic.core; Yaml and Capn Proto. According to the API specs, the Yaml serialization is depreciated and the Capn Proto serialization is the one to use. Should we remove Yaml entirely and clean up the code?

The Capn Proto serialization is the most confusing. Fortunately Capn Proto does must of the work generating C++ and .h files to handle this process. If the CMake files are correct, it should just work. The API user just calls the writeToFile() and readFromFile() routines to make this happen.

However, there are write() and read() functions on many classes that “write the instance to the specified pycapnp builder” and “returns a new instance using the state saved to the specified pycapnp reader”. This uses the pycapnp dependancy. This sounds like a C++ to Python interface. What is this used for?

How are we to create any other language interface (or even an C++ client interface) if this functionality is required? Do we have to write one of these for C#?

This seems to go against the spirit of the overall API spec where only simple data types are exchanged between languages. If a client language wants to obtain or pass a class it should be passing opaque pointers to and from the nupic.core. Operations on the class would be performed by the nupic.core code. If this is the intent then why do we need to serialize a class and pass it to Python?

@David_Keeney I really do not have any look on Yaml and Capn Proto. If they are for serialization only, in other projects of mine we use CEREAL - c++ lightweight and independent header file only. I think cereal is a good choice for us!

1 Like

@David_Keeney I’m took a closer look into your community fork. One question. When you say you need to compile with python 3.x, how come there are still python 2.7x C API calls in your source code? For instance, here

Ok, I cheated. If you look at the new file PythonCompatability.h you will find that I used a macro to change all of the 2.7 version calls to 3.3+ version calls. The coding standard says not to use macros so you are right, I should manually change all of the 2.7 version calls to 3.3+ version calls in the Python support routines.

At the time I was finding some 2.7 version calls in some of the generated code. It turns out that with the new versions of Capnproto its generated code contains conditional compiles that pick the right routines. So I should go back and remove the macros.

Thanks for holding me to the standard.

Ok, if it works it’s fine for now. I’m working on a solution to rid nupic from all Python’s C API calls using pybind11. That would also mean that the data structures in src/nupic/py_support and more might not be needed anymore.

At some point we could merged that into your solution.