Repository: bab2min/tomotopy (language: python)

Issue:
Segmentation fault when calling `infer` on untrained loaded model
Hey @bab2min, wanted to report a segfault with the following code:

```python
import tomotopy as tp

model = tp.LDAModel()
model.save("/tmp/model.bin")

model = tp.LDAModel.load("/tmp/model.bin")
doc = model.make_doc(["unseen", "document"])
model.infer(doc)
```

tomotopy 0.12.4


Discussion / hints:

Fix patch:
diff --git a/src/python/py_LDA.cpp b/src/python/py_LDA.cpp
index 796bb09..22f64cd 100644
--- a/src/python/py_LDA.cpp
+++ b/src/python/py_LDA.cpp
@@ -297,6 +297,11 @@ static PyObject* LDA_save(TopicModelObject* self, PyObject* args, PyObject *kwar
 	return py::handleExc([&]()
 	{
 		if (!self->inst) throw py::RuntimeError{ "inst is null" };
+		if (!self->isPrepared)
+		{
+			self->inst->prepare(true, self->minWordCnt, self->minWordDf, self->removeTopWord);
+			self->isPrepared = true;
+		}
 		ofstream str{ filename, ios_base::binary };
 		if (!str) throw py::OSError{ std::string("cannot open file '") + filename + std::string("'") };
 
@@ -330,6 +335,11 @@ static PyObject* LDA_saves(TopicModelObject* self, PyObject* args, PyObject* kwa
 	return py::handleExc([&]()
 	{
 		if (!self->inst) throw py::RuntimeError{ "inst is null" };
+		if (!self->isPrepared)
+		{
+			self->inst->prepare(true, self->minWordCnt, self->minWordDf, self->removeTopWord);
+			self->isPrepared = true;
+		}
 		ostringstream str;
 
 		vector<uint8_t> extra_data;
diff --git a/src/python/py_utils.cpp b/src/python/py_utils.cpp
index 88415fb..41071bf 100644
--- a/src/python/py_utils.cpp
+++ b/src/python/py_utils.cpp
@@ -603,7 +603,7 @@ PyObject* CorpusObject::concatNgrams(CorpusObject* self, PyObject* args, PyObjec
 						size_t found = nnode->val - 1;
 						doc.words[i] = pcandVids[found];
 						size_t len = pcands[found].w.size();
-						if(len > 1) doc.words.erase(doc.words.begin() + i - len + 1, doc.words.begin() + i);
+						if(len > 1) doc.words.erase(doc.words.begin() + i + 1 - len, doc.words.begin() + i);
 						totUpdated++;
 					}
 				}


Test patch:
diff --git a/test/unit_test.py b/test/unit_test.py
index 9edd95f..c55f1c7 100644
--- a/test/unit_test.py
+++ b/test/unit_test.py
@@ -246,6 +246,14 @@ def infer_together(cls, inputFile, mdFields, f, kargs, ps):
             unseen_docs[n] = mdl.make_doc(ch)
 
     mdl.infer(unseen_docs, parallel=ps, together=True)
+    
+def test_issue197():
+    model = tp.LDAModel()
+    model.save("./model.bin")
+
+    model = tp.LDAModel.load("./model.bin")
+    doc = model.make_doc(["unseen", "document"])
+    model.infer(doc)
 
 def test_issue_187_crash_exc():
     mdl = tp.LDAModel(k=10)