diff --git a/.gitignore b/.gitignore
index d49391c..19f729d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,277 @@
-.spyproject/
+# Created by https://www.toptal.com/developers/gitignore/api/python,pycharm
+# Edit at https://www.toptal.com/developers/gitignore?templates=python,pycharm
-__pycache__
+### PyCharm ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### PyCharm Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+pytestdebug.log
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+doc/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+#poetry.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+# .env
+.env/
+.venv/
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+pythonenv*
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# operating system-related files
+*.DS_Store #file properties cache/storage on macOS
+Thumbs.db #thumbnail cache on Windows
+
+# profiling data
+.prof
+
+
+# End of https://www.toptal.com/developers/gitignore/api/python,pycharm
# test output
-test/*/*/fail
-#test/*/*/*_data
-test/*/*/output*
-test/*/*/rawout*
-test/*/*/regenSummary
-test/*/*/startRPD*
-test/*/*/witness_superset*
+test/data/zero_dim/**/failed_paths
+test/data/zero_dim/**/final_parameters
+test/data/zero_dim/**/finite_solutions
+test/data/zero_dim/**/function
+test/data/zero_dim/**/main_data
+test/data/zero_dim/**/midpath_data
+test/data/zero_dim/**/nonsingular_solutions
+test/data/zero_dim/**/raw_data
+test/data/zero_dim/**/raw_solutions
+test/data/zero_dim/**/real_finite_solutions
+test/data/zero_dim/**/singular_solutions
+test/data/zero_dim/**/start
+test/data/zero_dim/**/start_parameters
+test/data/zero_dim/**/output
+
+test/data/pos_dim/*/fail
+test/data/pos_dim/basic_pos_dim/witness_data
+test/data/pos_dim/*/rawout*
+test/data/pos_dim/*/regenSummary
+test/data/pos_dim/*/startRPD*
+test/data/pos_dim/*/witness_superset*
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..3b1f3d3
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+python-bertini
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ad684c6
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..97acf69
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/other.xml b/.idea/other.xml
new file mode 100644
index 0000000..640fd80
--- /dev/null
+++ b/.idea/other.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/python-bertini.iml b/.idea/python-bertini.iml
new file mode 100644
index 0000000..4323654
--- /dev/null
+++ b/.idea/python-bertini.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..58114f4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,25 @@
+# python-bertini
+
+python-bertini is a Python library for numerical algebraic geometry.
+Mostly, it's just a wrapper around [Bertini](https://bertini.nd.edu) (sold separately).
+
+## Installing python-bertini
+
+Don't install python-bertini.
+It's not ready yet.
+If you want something right now, and you're into Julia, you might try [Bertini.jl](https://github.com/PBrdng/Bertini.jl).
+
+If you absolutely must, then clone this repository, cd to the base directory, and run either
+
+```shell
+$ conda env create -n bertini -f environment.yml # if you have anaconda
+```
+or (with your virtualenv activated)
+```shell
+$ pip install -U -r requirements.txt # if you just want to use a virtualenv
+```
+
+Then in either case run
+```shell
+$ pip install -e .
+```
\ No newline at end of file
diff --git a/naglib/__init__.py b/bertini/__init__.py
similarity index 100%
rename from naglib/__init__.py
rename to bertini/__init__.py
diff --git a/naglib/exceptions.py b/bertini/exceptions.py
similarity index 81%
rename from naglib/exceptions.py
rename to bertini/exceptions.py
index 9add824..2e25de9 100644
--- a/naglib/exceptions.py
+++ b/bertini/exceptions.py
@@ -7,13 +7,15 @@ def __init__(self, message):
def __str__(self):
return self.message
-
+
+
class AffineInfinityException(NAGlibBaseException):
"""
"""
def __init__(self, message):
super(AffineInfinityException, self).__init__(message)
-
+
+
class BertiniError(Exception):
"""
BertiniError
@@ -22,23 +24,15 @@ class BertiniError(Exception):
"""
def __init__(self, message):
super(BertiniError, self).__init__(message)
-
+
+
class ExitSpaceError(NAGlibBaseException):
"""
"""
def __init__(self, message):
super(ExitSpaceError, self).__init__(message)
-class NoBertiniException(NAGlibBaseException):
- """
- NoBertiniException
-
- Raise NoBertiniException when Bertini can't be located on the system
- """
- def __init__(self):
- message = "you don't seem to have Bertini installed anywhere I can find it"
- super(NoBertiniException, self).__init__(message)
-
+
class NonPolynomialException(NAGlibBaseException):
"""
NonPolynomialException
@@ -48,7 +42,8 @@ class NonPolynomialException(NAGlibBaseException):
"""
def __init__(self, message):
super(NonPolynomialException, self).__init__(message)
-
+
+
class NonHomogeneousException(NAGlibBaseException):
"""
NonHomogeneousException
@@ -58,13 +53,15 @@ class NonHomogeneousException(NAGlibBaseException):
"""
def __init__(self, message):
super(NonHomogeneousException, self).__init__(message)
-
+
+
class UnclassifiedException(NAGlibBaseException):
"""
"""
def __init__(self, message):
super(UnclassifiedException, self).__init__(message)
-
+
+
class WitnessDataException(NAGlibBaseException):
"""
"""
diff --git a/naglib/bertini/__init__.py b/bertini/io/__init__.py
similarity index 100%
rename from naglib/bertini/__init__.py
rename to bertini/io/__init__.py
diff --git a/bertini/io/input_file/__init__.py b/bertini/io/input_file/__init__.py
new file mode 100644
index 0000000..50b6cb3
--- /dev/null
+++ b/bertini/io/input_file/__init__.py
@@ -0,0 +1,2 @@
+from .config_section import BertiniConfig
+from .input_section import BertiniInput
diff --git a/bertini/io/input_file/config_section.py b/bertini/io/input_file/config_section.py
new file mode 100644
index 0000000..724e034
--- /dev/null
+++ b/bertini/io/input_file/config_section.py
@@ -0,0 +1,185 @@
+from copy import deepcopy
+
+from bertini.io.input_file.input_section import PARAMETERS, _validate_param
+
+
+class BertiniConfig(object):
+ TEVALP = -4
+ TEVALPJ = -3
+ TNEWTP = -2
+ TNEWTPJ = -1
+ TZERODIM = 0 # parallel
+ TPOSDIM = 1 # parallel
+ TSAMPLE = 2
+ TMEMTEST = 3
+ TPRINTWS = 4
+ TPROJECT = 5
+ TISOSTAB = 6
+ TREGENEXT = 7 # parallel
+
+ def __init__(self, **kwargs):
+ for arg_name in PARAMETERS:
+ if arg_name in kwargs:
+ arg_val = kwargs.pop(arg_name)
+ self.__setattr__(arg_name, arg_val)
+ else:
+ self.__setattr__(arg_name, deepcopy(PARAMETERS[arg_name]["default"]))
+
+ if kwargs:
+ key, _ = kwargs.popitem()
+ raise AttributeError(f"BertiniConfig has no attribute '{key}'")
+
+ self._validate()
+
+ def __str__(self):
+ s = "CONFIG\n"
+ for key, val in PARAMETERS.items():
+ instance_val = self.__getattribute__(key)
+ if instance_val != val["default"]:
+ s += f"{key}:{instance_val};\n"
+ s += "END;"
+ return s
+
+ def _validate(self):
+ """Ensure combinations of parameters play nicely."""
+ if self.mptype != 1 and self.precision != PARAMETERS["precision"]["default"]:
+ raise ValueError("you have set a non-default precision but have specified "
+ f"{'double' if self.mptype == 0 else 'adaptive'} precision")
+
+ def needs_component(self):
+ return self.tracktype in (self.TSAMPLE, self.TMEMTEST, self.TPRINTWS,
+ self.TPROJECT, self.TREGENEXT)
+
+ def needs_start_points(self):
+ nsp = self.tracktype in (self.TEVALP, self.TEVALPJ, self.TNEWTP, self.TNEWTPJ, self.TMEMTEST,
+ self.TISOSTAB) or self.parameterhomotopy == 2
+ return nsp
+
+ def needs_sample_count(self):
+ return self.tracktype == self.TSAMPLE
+
+ def needs_projection_variables(self):
+ return self.tracktype == self.TPROJECT
+
+ @property
+ def ampmaxprec(self):
+ return self._ampmaxprec
+
+ @ampmaxprec.setter
+ def ampmaxprec(self, val):
+ val, is_valid = _validate_param("ampmaxprec", val)
+ if not is_valid:
+ raise ValueError("ampmaxprec must be an integer greater than or equal to 64")
+ self._ampmaxprec = val
+
+ @property
+ def coeffbound(self):
+ return self._coeffbound
+
+ @coeffbound.setter
+ def coeffbound(self, val):
+ val, is_valid = _validate_param("coeffbound", val)
+ if not is_valid:
+ raise ValueError("coeffbound must be a positive double")
+ self._coeffbound = val
+
+ @property
+ def degreebound(self):
+ return self._degreebound
+
+ @degreebound.setter
+ def degreebound(self, val):
+ val, is_valid = _validate_param("degreebound", val)
+ if not is_valid:
+ raise ValueError("degreebound must be a positive double")
+ self._degreebound = val
+
+ @property
+ def finaltol(self):
+ return self._finaltol
+
+ @finaltol.setter
+ def finaltol(self, val):
+ val, is_valid = _validate_param("finaltol", val)
+ if not is_valid:
+ raise ValueError("finaltol must be a positive double")
+ self._finaltol = val
+
+ @property
+ def imagthreshold(self):
+ return self._finaltol
+
+ @imagthreshold.setter
+ def imagthreshold(self, val):
+ val, is_valid = _validate_param("imagthreshold", val)
+ if not is_valid:
+ raise ValueError("imagthreshold must be a positive double")
+ self._imagthreshold = val
+
+ @property
+ def mptype(self):
+ return self._mptype
+
+ @mptype.setter
+ def mptype(self, val):
+ val, is_valid = _validate_param("mptype", val)
+ if not is_valid:
+ raise ValueError(
+ f"mptype must take one of the following values: {','.join(map(str, range(0, 3)))}")
+ self._mptype = val
+
+ @property
+ def parameterhomotopy(self):
+ return self._parameterhomotopy
+
+ @parameterhomotopy.setter
+ def parameterhomotopy(self, val):
+ val, is_valid = _validate_param("parameterhomotopy", val)
+ if not is_valid:
+ raise ValueError(
+ f"parameterhomotopy must take one of the following values: {','.join(map(str, range(0, 3)))}")
+ self._parameterhomotopy = val
+
+ @property
+ def precision(self):
+ return self._precision
+
+ @precision.setter
+ def precision(self, val):
+ val, is_valid = _validate_param("precision", val)
+ if not is_valid:
+ raise ValueError("precision must be an integer greater than or equal to 64")
+ self._precision = val
+
+ @property
+ def randomseed(self):
+ return self._randomseed
+
+ @randomseed.setter
+ def randomseed(self, val):
+ val, is_valid = _validate_param("randomseed", val)
+ if not is_valid:
+ raise ValueError("randomseed must be a nonnegative integer")
+ self._randomseed = val
+
+ @property
+ def tracktolbeforeeg(self):
+ return self._tracktolbeforeeg
+
+ @tracktolbeforeeg.setter
+ def tracktolbeforeeg(self, val):
+ val, is_valid = _validate_param("tracktolbeforeeg", val)
+ if not is_valid:
+ raise ValueError(f"tracktolbeforeeg must be a positive double")
+ self._tracktolbeforeeg = val
+
+ @property
+ def tracktype(self):
+ return self._tracktype
+
+ @tracktype.setter
+ def tracktype(self, val):
+ val, is_valid = _validate_param("tracktype", val)
+ if not is_valid:
+ raise ValueError(f"tracktype must take one of the following values: {','.join(map(str, range(-4, 7)))}")
+ self._tracktype = int(val)
diff --git a/bertini/io/input_file/input_section.py b/bertini/io/input_file/input_section.py
new file mode 100644
index 0000000..3e58777
--- /dev/null
+++ b/bertini/io/input_file/input_section.py
@@ -0,0 +1,282 @@
+from copy import deepcopy
+from collections import OrderedDict
+from numbers import Number
+
+
+def _list_of_str(obj):
+ return isinstance(obj, list) and all(isinstance(x, str) for x in obj)
+
+
+def _list_of_lists_of_str(obj):
+ return isinstance(obj, list) and all(_list_of_str(l) for l in obj)
+
+
+def _dict_of_type(obj, dtype):
+ return isinstance(obj, dict) and _list_of_str(list(obj.keys())) \
+ and all((isinstance(v, dtype) or v is None) for v in obj.values())
+
+
+def _ordereddict_of_type(obj, dtype):
+ return isinstance(obj, OrderedDict) and _list_of_str(list(obj.keys())) \
+ and all((isinstance(v, dtype) or v is None) for v in obj.values())
+
+
+PARAMETERS = OrderedDict(tracktype={"default": 0,
+ "is valid": lambda x: x in range(-4, 8)},
+ tracktolbeforeeg={"default": 1e-11,
+ "is valid": lambda x: isinstance(x, Number) and x > 0},
+ mptype={"default": 2,
+ "is valid": lambda x: x in range(0, 3)},
+ precision={"default": 96,
+ "is valid": lambda x: isinstance(x, int) and x >= 64},
+ coeffbound={"default": 1000., # default for user-defined homotopies only
+ "is valid": lambda x: isinstance(x, float) and x > 0},
+ degreebound={"default": 5., # default for user-defined homotopies only
+ "is valid": lambda x: isinstance(x, float) and x > 0},
+ ampmaxprec={"default": 1024,
+ "is valid": lambda x: isinstance(x, int) and x >= 64},
+ finaltol={"default": 1.,
+ "is valid": lambda x: isinstance(x, Number) and x > 0},
+ imagthreshold={"default": 1.,
+ "is valid": lambda x: isinstance(x, Number) and x > 0},
+ parameterhomotopy={"default": 0,
+ "is valid": lambda x: x in range(0, 3)},
+ randomseed={"default": 0,
+ "is valid": lambda x: isinstance(x, int) and x >= 0})
+
+
+def _validate_param(name, val):
+ if name not in PARAMETERS:
+ return val, False
+
+ default_val = PARAMETERS[name]["default"]
+ is_valid = PARAMETERS[name]["is valid"]
+ if not isinstance(val, type(default_val)):
+ try:
+ val = type(default_val)(val) # cast val to the same type as default_val
+ except ValueError: # failed to cast
+ return val, False
+
+ return val, is_valid(val)
+
+
+INPUT_TYPES = OrderedDict(variable_group={"default": [],
+ "is valid": _list_of_lists_of_str},
+ variable={"default": [],
+ "is valid": _list_of_lists_of_str},
+ hom_variable_group={"default": [],
+ "is valid": _list_of_lists_of_str},
+ pathvariable={"default": [],
+ "is valid": _list_of_str},
+ random={"default": [],
+ "is valid": _list_of_str},
+ random_real={"default": [],
+ "is valid": _list_of_str},
+ constant={"default": {},
+ "is valid": lambda x: _dict_of_type(x, Number)},
+ subfunction={"default": {},
+ "is valid": lambda x: _dict_of_type(x, str)},
+ parameter={"default": OrderedDict(),
+ "is valid": lambda x: _ordereddict_of_type(x, str)},
+ function={"default": OrderedDict(),
+ "is valid": lambda x: _ordereddict_of_type(x, str)})
+
+
+class BertiniInput(object):
+ def __init__(self, **kwargs):
+ for arg_name in INPUT_TYPES:
+ if arg_name in kwargs:
+ arg_val = kwargs.pop(arg_name)
+ self.__setattr__(arg_name, arg_val)
+ else:
+ self.__setattr__(arg_name, deepcopy(INPUT_TYPES[arg_name]["default"]))
+
+ if kwargs:
+ key, _ = kwargs.popitem()
+ raise AttributeError(f"BertiniInput has no attribute '{key}'")
+
+ self._validate()
+
+ def __str__(self):
+ s = "INPUT\n"
+ # name declarations
+ if self.variable_group:
+ for variable_group in self.variable_group:
+ s += f"variable_group {','.join(variable_group)};\n"
+
+ if self.variable:
+ for variable in self.variable:
+ s += f"variable {','.join(variable)};\n"
+
+ if self.hom_variable_group:
+ for hom_variable_group in self.hom_variable_group:
+ s += f"hom_variable_group {','.join(hom_variable_group)};\n"
+
+ if self.pathvariable:
+ for pathvariable in self.pathvariable:
+ s += f"pathvariable {','.join(pathvariable)};\n"
+
+ if self.random:
+ for random in self.random:
+ s += f"random {','.join(random)};\n"
+
+ if self.random_real:
+ for random_real in self.random_real:
+ s += f"random_real {','.join(random_real)};\n"
+
+ if self.parameter:
+ parameters = ",".join(self.parameter.keys())
+ s += f"parameter {parameters};\n"
+
+ if self.constant:
+ constant = ",".join(self.constant.keys())
+ s += f"constant {constant};\n"
+
+ function = ",".join(self.function.keys())
+ s += f"function {function};\n"
+
+ # optional assignments (parameters, constants, &c.)
+ if self.parameter:
+ for key, val in self.parameter.items():
+ if val is None:
+ continue
+ s += f"{key} = {val};\n"
+
+ if self.constant:
+ for key, val in self.constant.items():
+ s += f"{key} = {val};\n"
+
+ if self.subfunction:
+ for key, val in self.subfunction.items():
+ s += f"{key} = {val};\n"
+
+ # function definitions
+ for key, val in self.function.items():
+ s += f"{key} = {val};\n"
+
+ s += "END;"
+
+ return s
+
+ def _validate(self):
+ if self.variable and (self.variable_group or self.hom_variable_group):
+ raise ValueError("specify EITHER variable OR some combination of variable_group and hom_variable_group")
+
+ @property
+ def variable_group(self):
+ return self._variable_group
+
+ @variable_group.setter
+ def variable_group(self, val):
+ is_valid = INPUT_TYPES["variable_group"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("variable_group must be a list of lists of str")
+ self._variable_group = val
+
+ @property
+ def variable(self):
+ return self._variable
+
+ @variable.setter
+ def variable(self, val):
+ is_valid = INPUT_TYPES["variable"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("variable must be a list of lists of str")
+ self._variable = val
+
+ @property
+ def hom_variable_group(self):
+ return self._hom_variable_group
+
+ @hom_variable_group.setter
+ def hom_variable_group(self, val):
+ is_valid = INPUT_TYPES["hom_variable_group"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("hom_variable_group must be a list of lists of str")
+ self._hom_variable_group = val
+
+ @property
+ def pathvariable(self):
+ return self._pathvariable
+
+ @pathvariable.setter
+ def pathvariable(self, val):
+ is_valid = INPUT_TYPES["pathvariable"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("pathvariable must be a list of str")
+ self._pathvariable = val
+
+ @property
+ def random(self):
+ return self._random
+
+ @random.setter
+ def random(self, val):
+ is_valid = INPUT_TYPES["random"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("random must be a list of str")
+ self._random = val
+
+ @property
+ def random_real(self):
+ return self._random_real
+
+ @random_real.setter
+ def random_real(self, val):
+ is_valid = INPUT_TYPES["random_real"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("random_real must be a list of str")
+ self._random_real = val
+
+ @property
+ def constant(self):
+ return self._constant
+
+ @constant.setter
+ def constant(self, val):
+ is_valid = INPUT_TYPES["constant"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("constant must be a dict of numeric")
+ self._constant = val
+
+ @property
+ def subfunction(self):
+ return self._subfunction
+
+ @subfunction.setter
+ def subfunction(self, val):
+ is_valid = INPUT_TYPES["subfunction"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("subfunction must be a dict of str")
+ self._subfunction = val
+
+ @property
+ def parameter(self):
+ return self._parameter
+
+ @parameter.setter
+ def parameter(self, val):
+ is_valid = INPUT_TYPES["parameter"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("parameter must be an OrderedDict of str")
+ self._parameter = val
+
+ @property
+ def function(self):
+ return self._function
+
+ @function.setter
+ def function(self, val):
+ is_valid = INPUT_TYPES["function"]["is valid"]
+ if not is_valid(val):
+ raise ValueError("function must be an OrderedDict of str")
+ self._function = val
+
+ @property
+ def ndims(self):
+ if self.variable:
+ nd = len(sum(self.variable, []))
+ else:
+ nd = len(sum(self.variable_group, []) + sum(self.hom_variable_group, []))
+
+ return nd
diff --git a/naglib/core/__init__.py b/bertini/io/reader.py
similarity index 100%
rename from naglib/core/__init__.py
rename to bertini/io/reader.py
diff --git a/bertini/io/result.py b/bertini/io/result.py
new file mode 100644
index 0000000..6b27057
--- /dev/null
+++ b/bertini/io/result.py
@@ -0,0 +1,45 @@
+from os import path as op
+
+from bertini.io.input_file.input_section import BertiniInput
+from bertini.io.input_file.config_section import BertiniConfig
+
+
+class BertiniResult:
+ def __init__(self, dirname, **kwargs):
+ """The output of a Bertini run.
+
+ Parameters
+ ----------
+ dirname : str
+ Path to directory where run was done.
+ kwargs
+ """
+ self._dirname = dirname
+
+ @property
+ def config(self):
+ """Configuration needed to reproduce the run."""
+ return self._config
+
+ @config.setter
+ def config(self, val):
+ assert isinstance(val, BertiniConfig)
+ self._config = val
+
+ @property
+ def dirname(self):
+ return self._dirname
+ @dirname.setter
+ def dirname(self, val):
+ assert op.isdir(val)
+ self._dirname = val
+
+ @property
+ def inputs(self):
+ """Inputs needed to reproduce the run."""
+ return self._inputs
+
+ @inputs.setter
+ def inputs(self, val):
+ assert isinstance(val, BertiniInput)
+ self._inputs = val
\ No newline at end of file
diff --git a/naglib/bertini/io.py b/bertini/io/utils.py
similarity index 62%
rename from naglib/bertini/io.py
rename to bertini/io/utils.py
index b48061c..4a463b8 100644
--- a/naglib/bertini/io.py
+++ b/bertini/io/utils.py
@@ -1,18 +1,22 @@
-from collections import deque, OrderedDict
+from _io import TextIOWrapper
+from collections import deque
from fractions import Fraction
import os.path as op
import sys
import re
-from typing import List, Tuple
+from typing import Tuple, Callable
import mpmath as mp
import numpy as np
-from naglib.exceptions import UnclassifiedException
+from bertini.io.input_file.input_section import BertiniInput
+from bertini.io.input_file.config_section import BertiniConfig
+from bertini.exceptions import UnclassifiedException
+from bertini.io.result import BertiniResult
-def _line_to_complex(line: str, multi: bool=False) -> complex:
+def _line_to_complex(line: str, multi: bool = False) -> complex:
real, imag = line.split(" ")
return mp.mpc(real, imag) if multi else np.complex(float(real), float(imag))
@@ -23,39 +27,29 @@ def _line_to_complex_rat(line: str) -> complex:
return np.complex(Fraction(real), Fraction(imag))
-def read_input_file(input_file: str) -> Tuple:
- """Parse input file.
+def parse_input_file(fh: TextIOWrapper, stop_if: Callable = None) -> Tuple[BertiniConfig, BertiniInput, list]:
+ """Given an open file handle, read until stopping criterion is satisfied
+ and try to parse an input file from it.
Parameters
----------
- input_file : str
- Path to input file.
+ fh : _io.TextIOWrapper
+ An open file handle.
+ stop_if : function, optional
+ Stop when the next line satisfies this function.
Returns
-------
- config : dict
+ config : BertiniConfig
Key-value pairs of parameters set in the CONFIG section.
- inputs : dict
+ inputs : BertiniInput
Values set in the INPUT section.
"""
+ if stop_if is None:
+ stop_if = lambda l: l == ""
- if not op.isfile(op.abspath(input_file)):
- raise IOError(f"Input file '{input_file}' not found")
-
- with open(input_file, "r") as fh:
- lines = deque([l.strip() for l in fh.readlines() if l != "\n"])
-
- config = {}
- inputs = dict(variable_group=deque(),
- variable=deque(),
- hom_variable_group=deque(),
- pathvariable=deque(),
- random=deque(),
- random_real=deque(),
- constant=OrderedDict(),
- function=OrderedDict(),
- parameter=OrderedDict(),
- subfunction=OrderedDict())
+ config = BertiniConfig()
+ inputs = BertiniInput()
misclines = []
in_config = in_input = False
@@ -68,93 +62,145 @@ def read_input_file(input_file: str) -> Tuple:
function_re = re.compile(r"^function\s+", re.I)
parameter_re = re.compile(r"^parameter\s+", re.I)
- while lines:
- line = lines.popleft().strip(" ;")
+ line = fh.readline()
+ while line and not stop_if(line):
+ line = line.strip()
if line.lower() == "config":
in_config = True
- continue
elif line.lower() == "input":
in_input = True
- continue
- elif line.lower() == "end":
+ elif line.lower().strip(";") == "end":
in_input = in_config = False
- continue
- elif line.startswith("%"):
- continue
-
- if in_config:
- key, val = map(lambda x: x.strip(), line.split(":"))
- val = val.split("%")[0].strip(" ;") # remove comment, semicolon, trailing whitespace
-
- if key.lower() in ["condnumthreshold", "endpointfinitethreshold", "finaltol",
- "pathtruncationthreshold", "samplefactor", "securitymaxnorm",
- "slicetolbeforeeg", "slicetolduringeg"]:
- val = float(val)
- elif key.lower() in ["coeffbound", "degreebound", "maxcodimension", "mptype",
- "parameterhomotopy", "precision", "randomseed", "securitylevel",
- "sharpendigits", "sharpenonly", "specificcodimension",
- "tracktype", "useregeneration", "userhomotopy", "witnessgentype",
- "witnesssupersetonly"]:
- val = int(val)
-
- config[key] = val
-
- elif in_input:
- if vargroup_re.match(line):
- line = vargroup_re.sub("", line)
- inputs["variable_group"].append(re.split(r",\s*", line))
- elif var_re.match(line):
- line = var_re.sub("", line)
- inputs["variable"].append(re.split(r",\s*", line))
- elif homvargroup_re.match(line):
- line = homvargroup_re.sub("", line)
- inputs["hom_variable_group"].append(re.split(r",\s*", line))
- elif pathvar_re.match(line):
- line = pathvar_re.sub("", line)
- inputs["pathvariable"].append(re.split(r",\s*", line))
- elif random_re.match(line):
- line = random_re.sub("", line)
- inputs["random"].append(re.split(r",\s*", line))
- elif constant_re.match(line):
- line = constant_re.sub("", line)
- constants = re.split(r",\s*", line)
- for c in constants:
- inputs["constant"][c] = None
- elif function_re.match(line):
- line = function_re.sub("", line)
- functions = re.split(r",\s*", line)
- for f in functions:
- inputs["function"][f] = None
- elif parameter_re.match(line):
- line = parameter_re.sub("", line)
- params = re.split(r",\s*", line)
- for p in params:
- inputs["parameter"][p] = None
- else:
- terms = re.split(r";\s*", line)
- for term in terms:
- # remove comments
- term = term.split("%")[0].strip()
- # split by =
- term = re.split(r"\s*=\s*", term)
- if len(term) != 2:
- misclines.append("=".join(term))
- else:
- term, val = term
- if term in inputs["constant"]:
- inputs["constant"][term] = val
- elif term in inputs["function"]:
- inputs["function"][term] = val
- elif term in inputs["parameter"]:
- inputs["parameter"][term] = val
+ elif not line.startswith("%") and len(line) > 0:
+ if not line.endswith(";"): # statement spans several lines
+ multiline = line
+ line = fh.readline()
+ while line and not line.endswith(";"):
+ multiline += " " + line.strip()
+ line = fh.readline()
+
+ line = multiline
+
+ line = line.strip(" ;")
+
+ if in_config:
+ key, val = map(lambda l: l.strip(), line.split(":"))
+ val = val.split("%")[0].strip(" ;") # remove comment, semicolon, trailing whitespace
+
+ setattr(config, key.lower(), val)
+
+ elif in_input:
+ if vargroup_re.match(line):
+ line = vargroup_re.sub("", line)
+ inputs.variable_group.append(re.split(r",\s*", line))
+ elif var_re.match(line):
+ line = var_re.sub("", line)
+ inputs.variable.append(re.split(r",\s*", line))
+ elif homvargroup_re.match(line):
+ line = homvargroup_re.sub("", line)
+ inputs.hom_variable_group.append(re.split(r",\s*", line))
+ elif pathvar_re.match(line):
+ line = pathvar_re.sub("", line)
+ inputs.pathvariable.append(re.split(r",\s*", line))
+ elif random_re.match(line):
+ line = random_re.sub("", line)
+ inputs.random.append(re.split(r",\s*", line))
+ elif constant_re.match(line):
+ line = constant_re.sub("", line)
+ constants = re.split(r",\s*", line)
+ for c in constants:
+ inputs.constant[c] = None
+ elif function_re.match(line):
+ line = function_re.sub("", line)
+ functions = re.split(r",\s*", line)
+ for f in functions:
+ inputs.function[f] = None
+ elif parameter_re.match(line):
+ line = parameter_re.sub("", line)
+ params = re.split(r",\s*", line)
+ for p in params:
+ inputs.parameter[p] = None
+ else:
+ terms = re.split(r";\s*", line)
+ for term in terms:
+ # remove comments
+ term = term.split("%")[0].strip()
+ # split by =
+ term = re.split(r"\s*=\s*", term)
+ if len(term) != 2:
+ misclines.append("=".join(term))
else:
- inputs["subfunction"][term] = val
+ term, val = term
+ if term in inputs.constant:
+ inputs.constant[term] = val
+ elif term in inputs.function:
+ inputs.function[term] = val
+ elif term in inputs.parameter:
+ inputs.parameter[term] = val
+ else:
+ inputs.subfunction[term] = val
+
+ line = fh.readline()
return config, inputs, misclines
-def read_points_file(points_file: str, tol: float=None) -> np.ndarray:
+def read_input_file(input_file: str) -> Tuple[BertiniConfig, BertiniInput, list]:
+ """Given a path to an input file, parse its contents.
+
+ Parameters
+ ----------
+ input_file : str
+ Path to input file.
+
+ Returns
+ -------
+ config : BertiniConfig
+ Key-value pairs of parameters set in the CONFIG section.
+ inputs : BertiniInput
+ Values set in the INPUT section.
+ """
+
+ if not op.isfile(op.abspath(input_file)):
+ raise IOError(f"Input file '{input_file}' not found")
+
+ with open(input_file, "r") as fh:
+ config, inputs, misclines = parse_input_file(fh)
+
+ return config, inputs, misclines
+
+
+def read_main_data_file(main_data_file: str) -> BertiniResult:
+ """
+
+ Parameters
+ ----------
+ main_data_file
+
+ Returns
+ -------
+ result : BertiniResult
+ """
+ if not op.isfile(main_data_file):
+ raise IOError(f"Main data file '{main_data_file}' not found")
+
+ result = BertiniResult(op.dirname(main_data_file))
+
+ with open(main_data_file, "r") as fh:
+ line = fh.readline()
+ # TODO: parse other more useful information from main_data
+ while line and line != "*************** input file needed to reproduce this run ***************\n":
+ line = fh.readline()
+
+ c, i, _ = parse_input_file(fh, lambda l: l == "*************** version information ***************")
+
+ result.config, result.inputs = c, i
+
+ return result
+
+
+def read_points_file(points_file: str, tol: float = None, multi: bool = False) -> np.ndarray:
"""Read points from an output file.
Parameters
@@ -164,6 +210,8 @@ def read_points_file(points_file: str, tol: float=None) -> np.ndarray:
tol : float, optional
If given, numbers smaller than this in absolute value will be set to 0.
Otherwise, they will be left as is.
+ multi : bool, optional
+ Use a multiple precision type if true (infer precision from string length)
Returns
-------
@@ -176,21 +224,34 @@ def read_points_file(points_file: str, tol: float=None) -> np.ndarray:
raise IOError(f"Points file '{points_file}' not found")
with open(points_file, "r") as fh:
- lines = [l.strip() for l in fh.readlines() if l != "\n"]
+ lines = [l.strip(";\n") for l in fh.readlines() if l != "\n"]
- n_points = int(lines[0])
+ n_points = int(lines.pop(0))
if n_points == 0:
- return np.zeros(0, dtype=np.complex) # return an empty array
+ return np.zeros(0, dtype=np.complex) # return an empty array
- lines = lines[1:]
n_lines = len(lines)
n_dims = n_lines // n_points
- points = np.zeros((n_dims, n_points), dtype=np.complex)
+ if multi: # peak ahead to get an idea of precision required
+ r = lines[0].split(" ")[0]
+ if "e" in r.lower(): # remove exponent
+ r = r[:r.lower().index("e")]
+ r = r.strip("-0").replace(".", "")
+
+ prec_est = int(np.floor(len(r) * np.log2(10)))
+
+ if mp.mp.prec < prec_est: # only ever raise working precision
+ mp.mp.prec = prec_est
+
+ if mp.mp.prec == 53: # default precision, just use doubles
+ multi = False
+
+ points = np.zeros((n_dims, n_points), dtype=mp.mpc if multi else np.complex)
for i in range(0, n_lines, n_dims):
point_lines = lines[i:i+n_dims]
- points[:, i//n_dims] = np.array([_line_to_complex(p) for p in point_lines])
+ points[:, i//n_dims] = np.array([_line_to_complex(p, multi) for p in point_lines])
if tol is not None:
points.imag[np.abs(points.imag) < tol] = 0
@@ -349,86 +410,28 @@ def read_witness_data_file(witness_data_file: str) -> list:
return codims
-def write_input_file(inputs: dict, config: dict, input_file: str):
+def write_input_file(config: BertiniConfig, inputs: BertiniInput, input_file: str):
"""Write a Bertini input file.
Parameters
----------
- inputs : dict
- Key-value pairs of input values.
- config : dict
- Key-value pairs of config values.
+ inputs : BertiniInput
+ Input values.
+ config : BertiniConfig
+ Config values.
input_file : str
Path to input file.
"""
with open(input_file, "w") as fh:
# config section
- print("CONFIG", file=fh)
-
- for key, val in config.items():
- print(f"{key}:{val};", file=fh)
-
- print("END", file=fh)
-
- print("INPUT", file=fh)
- # name declarations
- if inputs["variable_group"]:
- for variable_group in inputs["variable_group"]:
- print(f"variable_group {','.join(variable_group)};", file=fh)
-
- if inputs["variable"]:
- for variable in inputs["variable"]:
- print(f"variable {','.join(variable)};", file=fh)
-
- if inputs["hom_variable_group"]:
- for hom_variable_group in inputs["hom_variable_group"]:
- print(f"hom_variable_group {','.join(hom_variable_group)};", file=fh)
-
- if inputs["pathvariable"]:
- for pathvariable in inputs["pathvariable"]:
- print(f"pathvariable {','.join(pathvariable)};", file=fh)
-
- if inputs["random"]:
- for random in inputs["random"]:
- print(f"random {','.join(random)};", file=fh)
-
- if inputs["random_real"]:
- for random_real in inputs["random_real"]:
- print(f"random_real {','.join(random_real)};", file=fh)
-
- if inputs["parameter"]:
- print(f"parameter {','.join(inputs['parameter'].keys())};", file=fh)
-
- if inputs["constant"]:
- print(f"constant {','.join(inputs['constant'].keys())};", file=fh)
-
-
- print(f"function {','.join(inputs['function'].keys())};", file=fh)
-
- # optional assignments (parameters, constants, &c.)
- if inputs["parameter"]:
- for key, val in inputs["parameter"].items():
- if val is None:
- continue
- print(f"{key} = {val};", file=fh)
+ print(config, file=fh)
- if inputs["constant"]:
- for key, val in inputs["constant"].items():
- print(f"{key} = {val};", file=fh)
+ # input section
+ print(inputs, file=fh)
- if inputs["subfunction"]:
- for key, val in inputs["subfunction"].items():
- print(f"{key} = {val};", file=fh)
- # function definitions
- for key, val in inputs["function"].items():
- print(f"{key} = {val};", file=fh)
-
- print("END", file=fh)
-
-
-def write_points_file(points: List[np.ndarray], points_file: str="") -> None:
+def write_points_file(points: np.ndarray, points_file: str = "") -> None:
"""Print a set of points in Bertini output fashion, optionally to a file.
Parameters
@@ -445,13 +448,18 @@ def write_points_file(points: List[np.ndarray], points_file: str="") -> None:
else:
fh = sys.stdout
- n_points = len(points)
+ if points.ndim == 1: # single point
+ points = points.reshape(points.size, 1)
+
+ n_dims, n_points = points.shape
+
print(f"{n_points}\n", file=fh)
- for p in points:
+ for j in range(n_points):
+ p = points[:, j]
real, imag = p.real, p.imag
- for i in range(real.size):
+ for i in range(n_dims):
print(f"{real[i]} {imag[i]}", file=fh)
print("", file=fh)
@@ -557,4 +565,35 @@ def write_witness_data_file(witness_data: dict, witness_data_file: str):
real, imag = P[j].as_real_imag()
fh.write('{0} {1}\n'.format(real, imag))
- fh.close()
\ No newline at end of file
+ fh.close()
+
+
+def extract_error_message(output: str) -> str:
+ """Extract Bertini error message.
+
+ Parameters
+ ----------
+ output : str
+ Bertini standard output.
+
+ Returns
+ -------
+ err_message: str
+ Just the relevant error text.
+ """
+ lines = output.splitlines()
+
+ idx = None
+ for l in lines:
+ if l.startswith("ERROR"):
+ idx = lines.index(l)
+
+ if idx is None:
+ return output
+ else:
+ lines = lines[idx:-1] # remove "Bertini will now exit due to this error"
+
+ # remove "ERROR: "
+ lines[0] = lines[0].replace("ERROR: ", "")
+
+ return "\n".join(lines)
diff --git a/naglib/release.py b/bertini/release.py
similarity index 100%
rename from naglib/release.py
rename to bertini/release.py
diff --git a/bertini/run.py b/bertini/run.py
new file mode 100644
index 0000000..cb16057
--- /dev/null
+++ b/bertini/run.py
@@ -0,0 +1,437 @@
+import os
+import os.path as op
+import multiprocessing
+import subprocess
+import sys
+import tempfile
+
+import numpy as np
+
+from typing import Union
+
+from bertini.io.input_file import BertiniInput, BertiniConfig
+from bertini.io.utils import (read_main_data_file, read_points_file, write_input_file, write_points_file,
+ extract_error_message)
+from bertini.exceptions import BertiniError
+
+
+def _which(exe: str) -> Union[str, None]:
+ if sys.platform == "win32":
+ which_exe = "where.exe"
+ else:
+ which_exe = "which"
+
+ try:
+ path = subprocess.check_output([which_exe, exe], stderr=subprocess.DEVNULL).splitlines()[0].decode()
+ except subprocess.CalledProcessError:
+ path = None
+
+ return path
+
+
+class BertiniRun:
+ def __init__(self, config, inputs, **kwargs):
+ """A single Bertini run.
+
+ Parameters
+ ----------
+ config : BertiniConfig
+ Options to pass to Bertini.
+ inputs : BertiniInput
+ Bertini input section.
+ **kwargs : Keyword arguments
+ Arguments required for specific run types.
+ """
+
+ self.config = config
+
+ if not isinstance(inputs, BertiniInput):
+ raise TypeError("inputs must be an instance of BertiniInput")
+ self._inputs = inputs
+
+ # can use MPI for these types of run
+ self._parallel = self.tracktype in (config.TZERODIM, config.TPOSDIM, config.TREGENEXT)
+
+ if config.needs_start_points():
+ if "start" not in kwargs:
+ raise ValueError("specify a point or points to evaluate with the keyword argument 'start'")
+ self.start = kwargs["start"]
+
+ if config.needs_component():
+ if "component" not in kwargs:
+ raise ValueError("specify a component with the keyword argument 'component'")
+ self._component = kwargs["component"]
+
+ if config.needs_sample_count():
+ if "sample" not in kwargs:
+ raise ValueError("specify how many points to sample with the keyword argument 'sample'")
+ self._sample = kwargs["sample"]
+
+ if config.needs_projection_variables():
+ if "projection" not in kwargs:
+ raise ValueError("specify the variables onto which you wish to project with the keyword argument "
+ "'projection'")
+ self._projection = kwargs["projection"]
+
+ # a setting of ParameterHomotopy > 0 requires parameters
+ if config.parameterhomotopy > 0 and not inputs.parameter:
+ raise ValueError("you are attempting a parameter homotopy with no parameters")
+
+ # conversely, the presence of parameters requires ParameterHomotopy > 0
+ if inputs.parameter and config.parameterhomotopy == 0:
+ raise ValueError("your system has parameters but you have not specified a parameter homotopy")
+
+ # parameterhomotopy:2 requires start and final params, also start points
+ if config.parameterhomotopy == 2:
+ if "start_parameters" in kwargs:
+ self.start_parameters = kwargs["start_parameters"]
+ else:
+ raise ValueError("you have selected parameterhomotopy:2 but you have not given start parameters")
+ if "final_parameters" in kwargs:
+ self.final_parameters = kwargs["final_parameters"]
+ else:
+ raise ValueError("you have selected parameterhomotopy:2 but you have not given final parameters")
+
+ if "bertini_path" in kwargs:
+ if not op.isfile(kwargs["bertini_path"]):
+ raise OSError(f"didn't find Bertini at '{kwargs['bertini_path']}'")
+ self._bertini = kwargs["bertini_path"]
+ else:
+ bertini = _which("io")
+ if bertini is None:
+ raise OSError("couldn't find a io executable and you didn't specify one")
+ self._bertini = bertini
+
+ if "mpi_path" in kwargs:
+ if kwargs["mpi_path"] is not None and not op.isfile(kwargs["mpi_path"]):
+ raise OSError(f"didn't find MPI executable at '{kwargs['mpi_path']}'")
+ self._mpi = kwargs["mpi_path"]
+ else:
+ self._mpi = _which("mpirun")
+
+ self._complete = False
+
+ def _recover_data(self):
+ """Recover data from a run.
+
+ Returns
+ -------
+ data : BertiniResult
+ """
+ if not self._complete:
+ return
+
+ result = read_main_data_file(op.join(self.dirname, "main_data"))
+
+ if self.tracktype == self.config.TZERODIM:
+ if op.isfile(op.join(self.dirname, "finite_solutions")):
+ result.finite_solutions = read_points_file(op.join(self.dirname, "finite_solutions"),
+ multi=self.config.mptype != 0)
+ else:
+ result.finite_solutions = np.array(0, dtype=np.complex)
+
+ if op.isfile(op.join(self.dirname, "real_finite_solutions")):
+ result.real_finite_solutions = read_points_file(op.join(self.dirname, "real_finite_solutions"),
+ multi=self.config.mptype != 0)
+ else:
+ result.real_finite_solutions = np.array(0, dtype=np.complex)
+
+ result.nonsingular_solutions = read_points_file(op.join(self.dirname, "nonsingular_solutions"),
+ multi=self.config.mptype != 0)
+ result.singular_solutions = read_points_file(op.join(self.dirname, "singular_solutions"),
+ multi=self.config.mptype != 0)
+
+ if self.config.parameterhomotopy == 1:
+ result.start_parameters = read_points_file(op.join(self.dirname, "start_parameters"), multi=True)
+ result.start = read_points_file(op.join(self.dirname, "start"), multi=self.config.mptype != 0)
+
+ return result
+
+ def _recover_input(self):
+ """Read main_data and recover input needed to reproduce this run.
+ """
+ filename = self._dirname + "/main_data"
+ key = "*************** input file needed to reproduce this run ***************\n"
+ try:
+ fh = open(filename, 'r')
+ lines = fh.readlines()
+ fh.close()
+ except IOError:
+ lines = []
+
+ try:
+ dex = lines.index(key)
+ except ValueError:
+ msg = 'no main_data file!'
+ raise BertiniError(msg)
+ inlines = lines[dex + 1:]
+ while inlines[0] == '\n':
+ inlines = inlines[1:]
+
+ dex = inlines.index('END;\n')
+ inlines = inlines[:dex + 1]
+
+ return inlines
+
+ # def _write_files(self):
+ # from io.io.fileutils import fprint
+ #
+ # tracktype = self._tracktype
+ # dirname = self._dirname
+ # system = self._system
+ # if not op.exists(dirname):
+ # os.mkdir(dirname)
+ #
+ # ### write the system
+ # sysconfig = self._config.copy()
+ # sysconfig.update({'TrackType':tracktype})
+ # inputf = self._write_system(system, config=sysconfig)
+ #
+ # ### write out `start', `start_parameters', `final_parameters'
+ # if '_start' in dir(self):
+ # start = self._start
+ # if self._tracktype == self.TMEMTEST:
+ # startfile = dirname + '/member_points'
+ # else:
+ # startfile = dirname + '/start'
+ # fprint(start, startfile)
+ # if self._parameter_homotopy:
+ # phtpy = self._parameter_homotopy
+ # pkeys = phtpy.keys()
+ # if 'start parameters' in pkeys:
+ # startp = phtpy['start parameters']
+ # startpfile = dirname + '/start_parameters'
+ # fprint(startp, startpfile)
+ # if 'final parameters' in pkeys:
+ # finalp = phtpy['final parameters']
+ # finalpfile = dirname + '/final_parameters'
+ # fprint(finalp, finalpfile)
+ #
+ # ### write out component information
+ # if '_component' in dir(self):
+ # component = self._component
+ # #cid = component.component_id
+ # dim = component.dim
+ # if tracktype == self.TREGENEXT:
+ # self._write_system(component.system, 'iold', {'TrackType':1})
+ # witness_data = component._construct_witness_data()
+ # self._write_witness_data(witness_data, dirname, filename='wdold')
+ # instructions = ['1', 'iold', 'wdold', str(dim), '0']
+ # self._write_instructions(instructions)
+ # elif tracktype in (self.TSAMPLE, self.TMEMTEST, self.TPRINTWS, self.TPROJECT):
+ # witness_data = component._construct_witness_data()
+ # self._write_witness_data(witness_data, dirname)
+ # if tracktype == self.TSAMPLE:
+ # sample = self._sample
+ # instructions = [str(dim), '0', str(sample), '0', 'sampled']
+ # self._write_instructions(instructions)
+ # elif tracktype == self.TPRINTWS:
+ # instructions = [str(dim), '0', 'points.out', 'sys.out']
+ # self._write_instructions(instructions)
+ # elif tracktype == self.TPROJECT:
+ # instructions = [str(dim), '0']
+ # self._write_instructions(instructions)
+ #
+ # ### write out projection information
+ # projection = self._projection
+ # projnum = ['1' if x in projection else '0' for x in system.variables]
+ # projnum = [' '.join(projnum)]
+ # self._write_instructions(projnum, 'projection')
+ #
+ # return inputf
+
+ def _write_instructions(self, lines, filename='instructions'):
+ filename = self._dirname + '/' + filename
+ fh = open(filename, 'w')
+ for line in lines:
+ fh.write(line + '\n')
+ fh.close()
+
+ def run(self, dirname: str = None, tee: bool = True):
+ """Run Bertini and collect results.
+
+ Parameters
+ ----------
+ dirname : str, optional
+ Path to working directory.
+ tee : bool, optional
+ Print to stdout as you go if true.
+ Returns
+ -------
+
+ """
+ # in case the user has changed any of these
+ if self._parallel and self._mpi is not None and multiprocessing.cpu_count() >= 2:
+ cmd = self._mpi
+ arg = [cmd, '-np', str(multiprocessing.cpu_count() // 2), self._bertini, "input"]
+ else:
+ arg = [self._bertini, "input"]
+
+ self.setup(dirname) # write files
+
+ if op.isfile(op.join(self.dirname, "/instructions")):
+ stdin = op.join(self.dirname, "/instructions")
+ else:
+ stdin = None
+
+ if stdin is not None:
+ stdin = open(stdin, "r")
+
+ try:
+ proc = subprocess.Popen(arg, stdin=stdin, stdout=subprocess.PIPE,
+ cwd=self.dirname, universal_newlines=True)
+ except subprocess.CalledProcessError as e:
+ msg = extract_error_message(e.output)
+ raise BertiniError(msg)
+
+ output = []
+ while True:
+ line = proc.stdout.readline()
+ if line == "" and proc.poll() is not None:
+ break
+
+ line = line.strip()
+ output.append(line)
+ if tee:
+ print(line)
+
+ if stdin is not None:
+ stdin.close()
+
+ self._complete = True
+ self._output = output
+
+ return self._recover_data()
+
+ def setup(self, dirname: str = None):
+ """Write input and instructions files to working directory.
+
+ Parameters
+ ----------
+ dirname : str
+ Path to directory to run Bertini.
+ """
+ # write input file
+ if dirname is None:
+ self._dirname = tempfile.mkdtemp()
+ elif not op.isdir(dirname):
+ os.makedirs(dirname)
+ self._dirname = dirname
+ else:
+ self._dirname = dirname
+
+ input_file = op.join(self._dirname, "input")
+ write_input_file(self.config, self.inputs, input_file)
+
+ if self.config.parameterhomotopy == 2:
+ write_points_file(self.start_parameters.reshape(1, self.start_parameters.size),
+ op.join(self._dirname, "start_parameters"))
+ write_points_file(self.final_parameters.reshape(1, self.final_parameters.size),
+ op.join(self._dirname, "final_parameters"))
+ write_points_file(self.start, op.join(self._dirname, "start"))
+
+ @property
+ def bertini(self):
+ return self._bertini
+
+ @bertini.setter
+ def bertini(self, val):
+ self._bertini = val
+
+ @property
+ def config(self):
+ return self._config
+
+ @config.setter
+ def config(self, val):
+ if not isinstance(val, BertiniConfig):
+ raise TypeError("config must be an instance of BertiniConfig")
+ self._config = val
+
+ @property
+ def complete(self):
+ return self._complete
+
+ @property
+ def dirname(self):
+ return self._dirname
+
+ @dirname.setter
+ def dirname(self, name):
+ self._dirname = name
+
+ @property
+ def inputs(self):
+ return self._inputs
+
+ @inputs.setter
+ def inputs(self, val):
+ if not isinstance(val, BertiniInput):
+ raise TypeError("inputs must be an instance of BertiniInput")
+ self._inputs = val
+
+ @property
+ def output(self):
+ return self._output
+
+ @property
+ def start(self):
+ if hasattr(self, "_start"):
+ return self._start
+ else:
+ return np.zeros(0, dtype=np.complex)
+
+ @start.setter
+ def start(self, val):
+ if not isinstance(val, np.ndarray):
+ raise TypeError("expected a numpy array")
+ if val.ndim == 1:
+ val = val.reshape(val.size, 1)
+ if val.shape[0] != self.inputs.ndims:
+ raise ValueError(f"expected points of dimension {self.inputs.ndims} but you specified {val.shape[0]}")
+
+ self._start = val.astype(np.complex)
+
+ @property
+ def start_parameters(self):
+ if hasattr(self, "_start_parameters"):
+ return self._start_parameters
+ else:
+ return np.zeros(0, dtype=np.complex)
+
+ @start_parameters.setter
+ def start_parameters(self, val):
+ if self.config.parameterhomotopy != 2:
+ raise ValueError("only specify start_parameters for parameterhomotopy:2")
+ if not isinstance(val, np.ndarray):
+ raise TypeError("expected a numpy array")
+ if val.size != len(self.inputs.parameter):
+ raise ValueError(f"expected {len(self.inputs.parameter)} parameters but you specified {val.size}")
+
+ self._start_parameters = val.astype(np.complex)
+
+ @property
+ def final_parameters(self):
+ if hasattr(self, "_final_parameters"):
+ return self._final_parameters
+ else:
+ return np.zeros(0, dtype=np.complex)
+
+ @final_parameters.setter
+ def final_parameters(self, val):
+ if self.config.parameterhomotopy != 2:
+ raise ValueError("only specify final_parameters for parameterhomotopy:2")
+ if not isinstance(val, np.ndarray):
+ raise TypeError("expected a numpy array")
+ if val.size != len(self.inputs.parameter):
+ raise ValueError(f"expected {len(self.inputs.parameter)} parameters but you specified {val.size}")
+
+ self._final_parameters = val.astype(np.complex)
+
+ @property
+ def tracktype(self):
+ return self.config.tracktype
+
+
+def parameter_homotopy(system: list):
+ pass
diff --git a/environment.yml b/environment.yml
index 265f051..6675e08 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,7 +1,9 @@
-name: naglib
+name: python-bertini
channels:
- defaults
- conda-forge
dependencies:
- python=3.*
- numpy
+- scipy
+- mpmath
\ No newline at end of file
diff --git a/naglib/bertini/run.py b/naglib/bertini/run.py
deleted file mode 100644
index bdb4cd8..0000000
--- a/naglib/bertini/run.py
+++ /dev/null
@@ -1,651 +0,0 @@
-# -*- coding: utf-8 -*-
-from collections import deque
-import os
-import os.path as op
-import subprocess
-import tempfile
-
-import numpy as np
-
-from naglib.bertini.io import read_input_file, read_witness_data_file
-from naglib.constants import TOL
-from naglib.system import BERTINI, MPIRUN, PCOUNT
-from naglib.exceptions import BertiniError, NoBertiniException
-
-
-class BertiniRun(object):
- TEVALP = -4
- TEVALPJ = -3
- TNEWTP = -2
- TNEWTPJ = -1
- TZERODIM = 0 # parallel
- TPOSDIM = 1 # parallel
- TSAMPLE = 2
- TMEMTEST = 3
- TPRINTWS = 4
- TPROJECT = 5
- TISOSTAB = 6
- TREGENEXT = 7 # parallel
-
- def __init__(self, **kwargs):
- """Construct a BertiniRun.
-
- Parameters
- ----------
- **kwargs
- Keyword arguments.
-
- config : dict
- Key-value pairs of configurations
- variable_group : list or deque
- Variable group(s)
- variable : list or deque
- Variables
- hom_variable_group : list or deque
- Homogeneous variables
- pathvariable : list or deque
- Path variables
- constant : dict
- Key-value pairs of constant symbols and their values
- random : list or deque
- Collection of complex-valued random variables
- random_real : list or deque
- Collection of complex-valued random variables
- function : dict
- Key-value pairs of function symbols and their values
- parameter : dict
- Key-value pairs of parameter symbols and their values
- """
-
- config = kwargs["config"] if "config" in kwargs else {}
- if not isinstance(config, dict):
- raise TypeError(f"config type '{type(config)}' not understood")
-
- variable_group = kwargs["variable_group"] if "variable_group" in kwargs else deque()
- if isinstance(variable_group, list):
- variable_group = deque(variable_group)
- elif not isinstance(variable_group, deque):
- raise TypeError(f"variable_group type '{type(variable_group)}' not understood")
-
- variable = kwargs["variable"] if "variable" in kwargs else deque()
- if isinstance(variable, list):
- variable = deque(variable)
- if not isinstance(variable, deque):
- raise TypeError(f"variable type '{type(variable)}' not understood")
-
- hom_variable_group = kwargs["hom_variable_group"] if "hom_variable_group" in kwargs else deque()
- if isinstance(hom_variable_group, list):
- hom_variable_group = deque(hom_variable_group)
- if not isinstance(hom_variable_group, deque):
- raise TypeError(f"hom_variable_group type '{type(hom_variable_group)}' not understood")
-
- pathvariable = kwargs["pathvariable"] if "pathvariable" in kwargs else deque()
- if isinstance(pathvariable, list):
- pathvariable = deque(pathvariable)
- if not isinstance(pathvariable, deque):
- raise TypeError(f"pathvariable type '{type(pathvariable)}' not understood")
-
- random = kwargs["random"] if "random" in kwargs else deque()
- if isinstance(random, list):
- random = deque(random)
- if not isinstance(random, deque):
- raise TypeError(f"random type '{type(random)}' not understood")
-
- random_real = kwargs["random_real"] if "random_real" in kwargs else deque()
- if isinstance(random_real, list):
- random_real = deque(random_real)
- if not isinstance(random_real, deque):
- raise TypeError(f"random_real type '{type(random_real)}' not understood")
-
-
- constant = kwargs["constant"] if "constant" in kwargs else {}
- if not isinstance(constant, dict):
- raise TypeError(f"constant type '{type(constant)}' not understood")
-
- function = kwargs["function"] if "function" in kwargs else {}
- if not isinstance(function, dict):
- raise TypeError(f"function type '{type(function)}' not understood")
-
- parameter = kwargs["parameter"] if "parameter" in kwargs else {}
- if not isinstance(parameter, dict):
- raise TypeError(f"parameter type '{type(parameter)}' not understood")
-
- self._config = dict([(k.lower(), config[k]) for k in config])
-
- # check tracktype, set values accordingly
- if "tracktype" not in config:
- config["tracktype"] = 0
-
- if config["tracktype"] not in range(-4, 8):
- raise ValueError("TrackType must be an integer between -4 and 7 (inclusive)")
-
- self._parallel = self.tracktype in (self.TZERODIM, self.TPOSDIM, self.TREGENEXT)
-
- # check to see if tracktype jives with kwargs
- msg = ""
- ## start point(s) required
- if self.tracktype in (self.TEVALP, self.TEVALPJ, self.TNEWTP, self.TNEWTPJ, self.TMEMTEST, self.TISOSTAB) and "start" not in kkeys:
- msg = "specify a point or points to evaluate with the keyword argument 'start'"
- elif "start" in kkeys:
- start = kwargs["start"]
- if type(start) not in (list, tuple):
- start = [start]
- self._start = start
- ## component required
- if tracktype in (self.TSAMPLE, self.TMEMTEST, self.TPRINTWS, self.TPROJECT, self.TREGENEXT) and 'component' not in kkeys:
- msg = "specify a component with the keyword argument 'component'"
- elif 'component' in kkeys:
- self._component = kwargs['component']
- ## sample count required
- if tracktype == self.TSAMPLE and 'sample' not in kkeys:
- msg = "specify how many points to sample with the keyword argument `sample'"
- elif tracktype == self.TSAMPLE:
- self._sample = kwargs['sample']
- ## projection variables required
- if tracktype == self.TPROJECT and 'projection' not in kkeys:
- msg = "specify the variables onto which you wish to project with the keyword argument `projection'"
- elif 'projection' in kkeys:
- self._projection = kwargs['projection']
- if msg:
- raise KeyError(msg)
-
- # tolerance
- # TODO:make this mean something
- if 'tol' in kkeys:
- self._tol = kwargs['tol']
- else:
- self._tol = TOL
-
- # parameter homotopy
- self._parameter_homotopy = {'key':'', 'arg':0}
- if 'parameterhomotopy' in ckeys:
- ckeys2 = config.keys()
- for k in ckeys2:
- if k.lower() == 'parameterhomotopy':
- self._parameter_homotopy['key'] = 'ParameterHomotopy'
- self._parameter_homotopy['arg'] = config[k] # in (0,1,2)
- break
-
- del ckeys2
-
- # ensure the system jives with the call for parameter homotopy
- msg = ''
- if not system.parameters and self._parameter_homotopy['arg'] > 0:
- msg = "you have attempted to define a parameter homotopy on a system with no parameters!"
- elif system.parameters and self._parameter_homotopy['arg'] <= 0:
- msg = "a parameterized system requires ParameterHomotopy either 1 or 2"
- elif tracktype != self.TZERODIM and self._parameter_homotopy['arg'] > 0:
- msg = "parameter homotopy only supported for zero-dimensional runs"
-
- if msg:
- raise KeyError(msg)
-
- if 'start' in kkeys:
- start = kwargs['start']
- if type(start) not in (tuple, list):
- start = [start]
- # this doesn't go in self._parameter_homotopy because other kinds of run use start files
- self._start = start
- if 'start_parameters' in kkeys:
- startp = kwargs['start_parameters']
- if type(startp) not in (tuple, list):
- startp = [startp]
- self._parameter_homotopy['start parameters'] = startp
- else:
- startp = None
- if 'final_parameters' in kkeys:
- finalp = kwargs['final_parameters']
- if type(finalp) not in (tuple, list):
- finalp = [finalp]
- self._parameter_homotopy['final parameters'] = finalp
- else:
- finalp = None
-
- # if a system specifies one of start parameters or final parameters it must specify the other
- if (startp and not finalp) or (finalp and not startp):
- msg = "specify both start parameters and final parameters or neither"
- raise BertiniError(msg)
-
- # user did not specify start or final parameters
- if 'parameterhomotopy' in ckeys and self._parameter_homotopy['arg'] > 1:
- if not (startp or finalp):
- msg = "specify start and/or final parameters with the keyword arguments `start_parameters' and/or `final_parameters'"
- raise KeyError(msg)
-
- self._dirname = tempfile.mkdtemp()
- self._bertini = BERTINI
- self._system = system
- self._config = config
- self._complete = False
- self._inputf = []
-
- def _recover_components(self, witness_data):
- """
- """
- from sympy import sympify
- from naglib.core.algebra import LinearSlice
- from naglib.core.base import AffinePoint, ProjectivePoint
- from naglib.core.geometry import IrreducibleComponent
- from naglib.core.witnessdata import WitnessPoint, WitnessSet
- system = self._system
- variables = system.variables
-# if system.homvar:
-# proj_dim = len(variables)
- #homsys = system
-# else:
-# proj_dim = len(system.variables) + 1
- #homsys = system.homogenize()
- homvar = sympify('_homvar')
- while homvar in system.variables:
- homvar = sympify('_' + str(homvar))
- homsys = system.homogenize(homvar)
- homvars = homsys.variables
-
- components = []
-
- for c in witness_data:
- codim = c['codim']
- homVarConst = c['homVarConst']
- points = c['points']
- coeffs = c['slice']
- rand_mat = c['A']
- homog_mat = c['W']
- homog_vec = c['H']
- hvc = c['homVarConst']
- patch_coeff = c['p']
-
- comp_isprojective = homVarConst == 0
-
- hslice = None
- if coeffs:
- if comp_isprojective:
- hslice = LinearSlice(coeffs, homvars, homvar)
- if not system.homvar:
- lslice = hslice.dehomogenize()
- else:
- lslice = LinearSlice(coeffs, variables)
- else:
- lslice = None
-
- dim_list = {}
-
- hcoord = None
- for point in points:
- comp_id = point['component number']
- if comp_isprojective:
- hcoord = point['coordinates']
- if not system.homvar:
- coord = ProjectivePoint(hcoord).dehomogenize()
- else:
- coord = AffinePoint(point['coordinates'])
-
- wpoint = WitnessPoint(coord, comp_id,
- corank=point['corank'],
- condition_number=point['condition number'],
- smallest_nonzero=point['smallest nonzero'],
- largest_zero=point['largest zero'],
- point_type=point['type'],
- multiplicity=point['multiplicity'],
- deflations=point['deflations'],
- precision=point['precision'],
- last_approximation=point['last approximation'],
- homogeneous_coordinates=hcoord)
-
- if comp_id not in dim_list:
- dim_list[comp_id] = []
-
- dim_list[comp_id].append(wpoint)
-
- for comp_id in dim_list.keys():
- ws = WitnessSet(system.copy(),
- lslice,
- dim_list[comp_id],
- witness_data,
- homogeneous_slice=hslice)
- component = IrreducibleComponent(ws, codim, comp_id,
- randomization_matrix=rand_mat,
- homogenization_matrix=homog_mat,
- homogenization_vector=homog_vec,
- homogenization_variable=hvc,
- patch_coefficients=patch_coeff)
-
- components.append(component)
-
- return components
-
- def _recover_data(self):
- """
- recover the information pertinent to a run
- """
-
- if not self._complete:
- return
-
- from naglib.bertini.fileutils import read_points_file
- from naglib.utils import striplines
- dirname = self._dirname
- system = self._system
- tol = self._tol
- tracktype = self._tracktype
- main_data = dirname + '/main_data'
- fh = open(main_data, 'r')
- self._main_data = striplines(fh.readlines())
- fh.close()
-
- projective = not not system.homvar
-
- if tracktype == self.TEVALP:
- pass
- elif tracktype == self.TEVALPJ:
- pass
- elif tracktype == self.TNEWTP:
- pass
- elif tracktype == self.TNEWTPJ:
- pass
- elif tracktype == self.TZERODIM:
- finites = dirname + '/finite_solutions'
- startp = dirname + '/start_parameters'
- finite_solutions = read_points_file(finites, tol=tol, projective=projective)
-
- ptype = self._parameter_homotopy['arg']
- if ptype == 1:
- start_parameters = read_points_file(startp, tol=tol, projective=projective)
- return finite_solutions, start_parameters
-
- return finite_solutions
- elif tracktype == self.TPOSDIM:
- wdfile = dirname + '/witness_data'
- self._witness_data = self.read_witness_data_file(wdfile)
- components = self._recover_components(self._witness_data)
-
- return components
- elif tracktype == self.TSAMPLE:
- wdfile = dirname + '/witness_data'
- self._witness_data = self.read_witness_data_file(wdfile)
- samplef = dirname + '/sampled'
- sampled = read_points_file(samplef, tol=tol, projective=projective)
-
- return sampled
- elif tracktype == self.TMEMTEST:
- from sympy import zeros
-
- wdfile = dirname + '/witness_data'
- self._witness_data = self.read_witness_data_file(wdfile)
- inmat = dirname + '/incidence_matrix'
- fh = open(inmat, 'r')
- lines = striplines(fh.readlines())
- fh.close()
-
- testcodim = self._component.codim
- testcid = 0 # component_id should be 0 after write
-
- testp = self._start
- if type(testp) not in (list, tuple):
- testp = [testp]
-
- nonempty_codims = int(lines[0])
- lines = lines[1:]
- # gather nonempty codims with component count for each
- ccounts = lines[:nonempty_codims]
- lines = lines[nonempty_codims:]
-
- ccounts = [tuple([int(d) for d in c.split(' ')]) for c in ccounts]
- # ordered list of codims with component ids, for matrix
- cids = [(c[0], j) for c in ccounts for j in range(c[1])]
- colcount = len(cids)
- dex = cids.index((testcodim, testcid))
-
- numpoints = int(lines[0])
- lines = lines[1:]
-
- inmat = zeros(numpoints, colcount)
- # populate incidence matrix
- for i in range(numpoints):
- line = lines[i].split(' ')
- row = [int(l) for l in line]
- for j in range(colcount):
- inmat[i,j] = row[j]
-
- if numpoints == 1:
- return inmat[0, dex] == 1
- else:
- ret = []
- for i in range(numpoints):
- ret.append(inmat[i, dex] == 1)
- return ret
-
- elif tracktype == self.TPRINTWS:
- pointsfile = dirname + '/points.out'
- #sysfile = dirname + '/sys.out'
-
- points = read_points_file(pointsfile, tol=tol, projective=projective)
- #TODO: parse linear system file and return a LinearSystem
-
- return points
- elif tracktype == self.TPROJECT:
- #TODO: implement
- pass
- elif tracktype == self.TISOSTAB:
- config = self._config
- ckeys = config.keys()
- lkeys = [k.lower() for k in ckeys]
- cws = None
- if 'constructwitnessset' in lkeys:
- for k in ckeys:
- if k.lower() == 'constructwitnessset':
- cws = k
- break
- if cws and config[cws] == 1:
- wdfile = dirname + '/witness_data'
- self._witness_data = self.read_witness_data_file(wdfile)
- components = self._recover_components(self._witness_data)
- return components
-
- #TODO: read isosingular_summary and maybe output_isosingular
- elif tracktype == self.TREGENEXT:
- wdfile = dirname + '/witness_data'
- self._witness_data = self.read_witness_data_file(wdfile)
- components = self._recover_components(self._witness_data)
-
- return components
-
- def _recover_input(self):
- """
- Reads main_data and recovers the input file
- needed to reproduce a run
- """
- filename = self._dirname + "/main_data"
- key = "*************** input file needed to reproduce this run ***************\n"
- try:
- fh = open(filename, 'r')
- lines = fh.readlines()
- fh.close()
- except IOError:
- lines = []
-
- try:
- dex = lines.index(key)
- except ValueError:
- msg = 'no main_data file!'
- raise BertiniError(msg)
- inlines = lines[dex+1:]
- while inlines[0] == '\n':
- inlines = inlines[1:]
-
- dex = inlines.index('END;\n')
- inlines = inlines[:dex+1]
-
- return inlines
-
- def _write_files(self):
- from os.path import exists
- from naglib.bertini.fileutils import fprint
-
- tracktype = self._tracktype
- dirname = self._dirname
- system = self._system
- if not op.exists(dirname):
- os.mkdir(dirname)
-
- ### write the system
- sysconfig = self._config.copy()
- sysconfig.update({'TrackType':tracktype})
- inputf = self._write_system(system, config=sysconfig)
-
- ### write out `start', `start_parameters', `final_parameters'
- if '_start' in dir(self):
- start = self._start
- if self._tracktype == self.TMEMTEST:
- startfile = dirname + '/member_points'
- else:
- startfile = dirname + '/start'
- fprint(start, startfile)
- if self._parameter_homotopy:
- phtpy = self._parameter_homotopy
- pkeys = phtpy.keys()
- if 'start parameters' in pkeys:
- startp = phtpy['start parameters']
- startpfile = dirname + '/start_parameters'
- fprint(startp, startpfile)
- if 'final parameters' in pkeys:
- finalp = phtpy['final parameters']
- finalpfile = dirname + '/final_parameters'
- fprint(finalp, finalpfile)
-
- ### write out component information
- if '_component' in dir(self):
- component = self._component
- #cid = component.component_id
- dim = component.dim
- if tracktype == self.TREGENEXT:
- self._write_system(component.system, 'iold', {'TrackType':1})
- witness_data = component._construct_witness_data()
- self._write_witness_data(witness_data, dirname, filename='wdold')
- instructions = ['1', 'iold', 'wdold', str(dim), '0']
- self._write_instructions(instructions)
- elif tracktype in (self.TSAMPLE, self.TMEMTEST, self.TPRINTWS, self.TPROJECT):
- witness_data = component._construct_witness_data()
- self._write_witness_data(witness_data, dirname)
- if tracktype == self.TSAMPLE:
- sample = self._sample
- instructions = [str(dim), '0', str(sample), '0', 'sampled']
- self._write_instructions(instructions)
- elif tracktype == self.TPRINTWS:
- instructions = [str(dim), '0', 'points.out', 'sys.out']
- self._write_instructions(instructions)
- elif tracktype == self.TPROJECT:
- instructions = [str(dim), '0']
- self._write_instructions(instructions)
-
- ### write out projection information
- projection = self._projection
- projnum = ['1' if x in projection else '0' for x in system.variables]
- projnum = [' '.join(projnum)]
- self._write_instructions(projnum, 'projection')
-
- return inputf
-
- def _write_instructions(self, lines, filename='instructions'):
- filename = self._dirname + '/' + filename
- fh = open(filename, 'w')
- for line in lines:
- fh.write(line + '\n')
- fh.close()
-
- def rerun(self, config={}):
- if not self._complete:
- return self.run()
- else:
- self._config.update(config)
- return self.run()
-
- def run(self, rerun_on_fail=False):
- # in case the user has changed any of these
- if not BERTINI:
- raise NoBertiniException()
-
- self._bertini = BERTINI
-
- if self._parallel and MPIRUN:
- cmd = MPIRUN
- arg = [cmd, '-np', str(PCOUNT), self._bertini]
- else:
- arg = [self._bertini]
-
- dirname = self._dirname
-
- input_file = self._write_files()
-
- if op.exists(dirname + '/instructions'):
- stdin = dirname + '/instructions'
- else:
- stdin = None
-
- arg += [input_file]
-
- os.chdir(dirname)
- if stdin:
- stdin = open(stdin, 'r')
- try:
- output = subprocess.check_output(arg, stdin=stdin, universal_newlines=True)
- except subprocess.CalledProcessError as e:
- msg = naglib.bertini.system.proc_err_output(e.output)
- raise BertiniError(msg)
-
- if stdin:
- stdin.close()
-
- self._complete = True
- self._output = output
-
- if rerun_on_fail:
- try:
- self._inputf = self._recover_input()
- data = self._recover_data()
- except:
- data = self.rerun()
- else:
- self._inputf = self._recover_input()
- data = self._recover_data()
-
- return data
-
- @property
- def bertini(self):
- return self._bertini
- @bertini.setter
- def bertini(self, bert):
- self._bertini = bert
-
- @property
- def complete(self):
- return self._complete
-
- @property
- def dirname(self):
- return self._dirname
- @dirname.setter
- def dirname(self, name):
- self._dirname = name
-
- @property
- def inputf(self):
- return self._inputf
-
- @property
- def output(self):
- return self._output
-
- @property
- def tracktype(self):
- return self._config["tracktype"]
- @tracktype.setter
- def tracktype(self, val):
- if val not in range(-4, 8):
- raise ValueError("tracktype must be an integer between -4 and 7 (inclusive)")
-
- self._config["tracktype"] = int(val)
-
-
-def parameter_homotopy(system: list):
- pass
\ No newline at end of file
diff --git a/naglib/constants.py b/naglib/constants.py
deleted file mode 100644
index 8885337..0000000
--- a/naglib/constants.py
+++ /dev/null
@@ -1,2 +0,0 @@
-"""Tolerance"""
-TOL = 1e-15
\ No newline at end of file
diff --git a/naglib/core/algebra.py b/naglib/core/algebra.py
deleted file mode 100644
index a16b881..0000000
--- a/naglib/core/algebra.py
+++ /dev/null
@@ -1,844 +0,0 @@
-from sympy import I, Matrix as spmatrix, sympify, zeros
-
-import naglib.bertini
-from naglib.constants import TOL
-from naglib.exceptions import BertiniError, NonPolynomialException, NonHomogeneousException
-from naglib.core.base import NAGObject, scalar_num, Point, AffinePoint
-
-class PolynomialSystem(NAGObject):
- """
- A polynomial system
- """
- def __init__(self, polynomials, variables=None, parameters=None, homvar=None):
- """
- Initialize the PolynomialSystem object
- """
- from re import sub as resub
- from functools import reduce
-
- if type(polynomials) == str:
- polynomials = [polynomials]
- try:
- polynomials = list(polynomials)
- except TypeError:
- polynomials = [polynomials]
-
- self._polynomials = []
-
- # check if any polynomial is a string and contains '^'
- for p in polynomials:
- if type(p) == str:
- p = resub(r'\^', r'**', p)
- p = sympify(p)
- self._polynomials.append(p)
-
- self._polynomials = spmatrix(self._polynomials)
-
- # check if any given functions are actually not polynomials
- for p in self._polynomials:
- if not p.is_polynomial():
- msg = "function {0} is not a polynomial".format(p)
- raise NonPolynomialException(msg)
-
- # set parameters, if given...
- if parameters:
- try:
- parameters = list(parameters)
- except TypeError:
- parameters = [parameters]
- parameters = [sympify(p) for p in parameters]
- self._parameters = spmatrix(parameters)
- # ...otherwise, set parameters to empty matrix
- else:
- self._parameters = spmatrix()
-
- # set variables, if given...
- if variables:
- try:
- variables = list(variables)
- except TypeError:
- variables = [variables]
- variables = [sympify(v) for v in variables]
- self._variables = spmatrix(variables)
- # ...otherwise, determine variables from non-parameter free symbols
- else:
- variable_list = set()
- param_set = set(self._parameters)
- # gather free symbols from each polynomial
- free_sym = [p.free_symbols for p in self._polynomials]
- if free_sym:
- variable_list = reduce(lambda x, y: x.union(y), free_sym)
- # remove parameters from set of free symbols
- variable_list = list(variable_list.difference(param_set))
- else:
- variable_list = []
- variable_strings = [str(v) for v in variable_list]
- variable_strings.sort()
- variables = sympify(variable_strings)
- self._variables = spmatrix(variables)
-
- # set homogenizing variable, if given
- if homvar:
- homvar = sympify(homvar)
- try: # multihomogeneous?
- homvar = list(homvar)
- except TypeError:
- homvar = [homvar]
- if len(homvar) > 1:
- msg = "multihomogeneous systems not yet supported"
- raise NotImplementedError(msg)
-
- # but check to see if it's legit
- if homvar[0] not in self._variables:
- msg = "homogenizing variable {0} not in variables".format(homvar)
- raise ValueError(msg)
-
- self._homvar = spmatrix(homvar)
- self._domain = len(self._variables) - 1
- else:
- self._homvar = spmatrix()
- self._domain = len(self._variables)
-
-
- d = []
- params = list(self._parameters)
- ones = [1 for param in params]
- paramsubs = zip(params,ones)
-
- # keep parameters out of degree calculation
- for poly in self._polynomials:
- p = poly.subs(paramsubs)
- if p.is_number: # p should never be a number, but...
- deg = 0
- else:
- polyp = p.as_poly(domain='CC')
- deg = polyp.total_degree()
- # check if polynomial is homogeneous
- if self._homvar:
- polyp = p.as_poly(domain='CC')
- if not polyp.is_homogeneous:
- msg = "polynomial {0} is not homogeneous".format(p)
- raise NonHomogeneousException(msg)
- d.append(deg)
-
- self._degree = tuple(d)
- self._num_variables = len(self._variables)
- self._num_polynomials = len(self._polynomials)
-
- def __str__(self):
- """
- x.__str__() <==> str(x)
- """
- polynomials = self._polynomials
- # even up the lengths of the polynomial strings
- pstrs = [str(p) for p in polynomials]
- #strlens = [len(f) for f in fstrs]
- #maxlen = max(strlens)
- #fstrs = [' '*(maxlen - len(f)) + f for f in fstrs]
- #fstr = '\n'.join(['[{0}]'.format(f) for f in fstrs])
- repstr = '{' + ', '.join([str(p) for p in pstrs]) + '}'
- return repstr
-
- def __repr__(self):
- """
- x.__repr__() <==> repr(x)
- """
- polynomials = list(self._polynomials)
- variables = list(self._variables)
- parameters = list(self._parameters)
- homvar = list(self._homvar)
- repstr = 'PolynomialSystem({0},{1},{2},{3})'.format(polynomials,
- variables,
- parameters,
- homvar)
-
- return repstr
-
- def __getitem__(self, key):
- """
- x.__getitem__(y) <==> x[y]
- """
- polynomials = self._polynomials
- return polynomials[key]
-
- def __getslice__(self, i, j):
- """
- x.__getslice__(i,j) <==> x[i:j]
- """
- polynomials = self._polynomials
- return spmatrix(polynomials[i:j])
-
- def __len__(self):
- return len(self._polynomials)
-
- def __eq__(self, other):
- return self.equals(other, strict=True)
-
- def __neg__(self):
- """
- x.__neg___() <==> -x
- """
- npolynomials = -self._polynomials
- variables = self._variables
- parameters = self._parameters
- homvar = self._homvar
- return PolynomialSystem(npolynomials, variables, parameters, homvar)
-
- def __add__(self, other):
- """
- x.__add__(y) <==> x + y
- """
- from functools import reduce
-
- if not isinstance(other, PolynomialSystem):
- t = type(other)
- msg = "unsupported operand type(s) for +: 'PolynomialSystem' and '{0}'".format(t)
- raise TypeError(msg)
-
- spoly = self._polynomials
- opoly = other._polynomials
- spolct = len(spoly)
- opolct = len(opoly)
-
- # different sizes of systems
- if spolct != opolct:
- msg = "can't add systems of different sizes; cowardly backing out"
- raise ValueError(msg)
-
- shomvar = self._homvar
- ohomvar = other._homvar
- sdeg = self._degree
- odeg = other._degree
-
- # check homogenizing variables
- if shomvar and ohomvar and shomvar == ohomvar:
- # both have same homogenizing variables and degrees; all is well
- if sdeg == odeg:
- svars = set(self._variables)
- ovars = set(other._variables)
- spars = set(self._parameters)
- opars = set(other._parameters)
-
- # ensure the parameters of x are not the variables of y
- if svars.intersection(opars) or spars.intersection(ovars):
- msg = "variables and parameters in summands overlap; cowardly backing out"
- raise ValueError(msg)
-
- newpoly = spoly + opoly
- newpsym = [p.free_symbols for p in newpoly]
- newpsym = reduce(lambda x, y: x.union(y), newpsym)
- newvars = (svars.union(ovars)).intersection(newpsym)
- newpars = (spars.union(opars)).intersection(newpsym)
- newvars = sorted([str(v) for v in newvars])
- newpars = sorted([str(p) for p in newpars])
- newvars = sympify(newvars)
- newpars = sympify(newpars)
-
- return PolynomialSystem(newpoly, newvars, newpars, shomvar)
- else:
- msg = "multihomogeneous systems not yet supported"
- raise NotImplementedError(msg)
- elif shomvar or ohomvar:
- msg = "multihomogeneous systems not yet supported"
- raise NotImplementedError(msg)
- else: # no homogenizing variables
- svars = set(self._variables)
- ovars = set(other._variables)
- spars = set(self._parameters)
- opars = set(other._parameters)
-
- # ensure the parameters of x are not the variables of y
- if svars.intersection(opars) or spars.intersection(ovars):
- msg = "variables and parameters in summands overlap; cowardly backing out"
- raise ValueError(msg)
-
- newpoly = spoly + opoly
- newpsym = [p.free_symbols for p in newpoly]
- newpsym = reduce(lambda x, y: x.union(y), newpsym)
- newvars = (svars.union(ovars)).intersection(newpsym)
- newpars = (spars.union(opars)).intersection(newpsym)
- newvars = sorted([str(v) for v in newvars])
- newpars = sorted([str(p) for p in newpars])
- newvars = sympify(newvars)
- newpars = sympify(newpars)
-
- return PolynomialSystem(newpoly, newvars, newpars)
-
- def __sub__(self, other):
- """
- x.__sub__(y) <==> x - y
- """
- if not isinstance(other, PolynomialSystem):
- t = type(other)
- msg = "unsupported operand type(s) for +: 'PolynomialSystem' and '{0}'".format(t)
- raise TypeError(msg)
-
- other = -other
- return self + other
-
- def __mul__(self, other):
- """
- x.__mul__(y) <==> x*y
- """
- from sympy import Add
- cls = self.__class__
-
- if isinstance(other, cls):
- sm = self.shape[0]
- om = other.shape[0]
- if sm > 1 and om > 1:
- from sympy import ShapeError
- msg = "shape mismatch"
- raise ShapeError(msg)
- elif sm == 1:
- spol = self.polynomials[0]
- opols = other.polynomials
- pols = spol*opols
- elif om == 1:
- opol = other.polynomials[0]
- spols = self.polynomials
- pols = opol*spols
-
- svars = set(self.variables)
- ovars = set(other.variables)
- spars = set(self.parameters)
- opars = set(other.parameters)
-
- if svars.intersection(opars) or ovars.intersection(spars):
- msg = "nontrivial intersection between variables and parameters"
- raise ValueError(msg)
- elif self._homvar != other.homvar:
- msg = "multihomogeneous polynomial systems not implemented yet"
- raise NotImplementedError(msg)
-
- variables = svars.union(ovars)
- parameters = spars.union(opars)
-
- return cls(pols, variables, parameters, self._homvar)
- elif isinstance(other, Add):
- parameters = self.parameters
- polynomials = self._polynomials * other
- homvar = self._homvar
-
- return cls(polynomials, parameters=parameters, homvar=homvar)
-
- elif scalar_num(other):
- polynomials = other*self._polynomials
- variables = self._variables
- parameters = self._parameters
- homvar = self._homvar
- if other == 0:
- return PolynomialSystem(polynomials)
- else:
- return PolynomialSystem(polynomials, variables, parameters, homvar)
- else:
- t = type(other)
- msg = "unsupported operand type(s) for *: 'PolynomialSystem' and '{0}'".format(t)
- raise TypeError(msg)
-
- def __rmul__(self, other):
- """
- x.__rmul__(y) <==> y*x
- """
- return self.__mul__(other)
-
- def __div__(self, other):
- """
- x.__div__(y) <==> x/y
- """
- return self.__truediv__(other)
-
- def __truediv__(self, other):
- """
- x.__truediv__(y) <==> x/y
- """
- if not scalar_num(other):
- t = type(other)
- msg = "unsupported operand type(s) for /: 'PolynomialSystem' and '{0}'".format(t)
- raise TypeError(msg)
- else:
- if other == 0:
- msg = "division by zero"
- raise ZeroDivisionError(msg)
- polynomials = self._polynomials/other
- variables = self._variables
- parameters = self._parameters
- homvar = self._homvar
- return PolynomialSystem(polynomials, variables, parameters, homvar)
-
- def assign_parameters(self, params):
- """
- Set params as parameters in self
- """
- if not hasattr(params, '__iter__'):
- params = [params]
- params = set(sympify(params))
-
- sparams = set(self._parameters).union(params)
- svars = set(self._variables).difference(sparams)
-
- str_pars = sorted([str(p) for p in sparams])
- str_vars = sorted([str(v) for v in svars])
-
- self._parameters = spmatrix(sympify(str_pars))
- self._variables = spmatrix(sympify(str_vars))
-
- def cat(self, other):
- """
- concatenate a polynomial at the end of self
- """
- if not other:
- return self
- other = sympify(other)
- try:
- other = spmatrix(other)
- except TypeError:
- other = spmatrix([other])
- parameters = self._parameters
- polynomials = self._polynomials
- homvar = self._homvar
-
- newpols = polynomials.col_join(other)
- return PolynomialSystem(newpols, parameters=parameters, homvar=homvar)
-
- def copy(self):
- polynomials = self._polynomials.copy()
- variables = self._variables.copy()
- parameters = self._parameters.copy()
- homvar = self._homvar.copy()
-
- return PolynomialSystem(polynomials, variables, parameters, homvar)
-
- def dehomogenize(self):
- """
- Dehomogenize the system
-
- If already nonhomogeneous, return self
- """
- hompolys = self._polynomials
- hompolys = spmatrix([p.expand() for p in hompolys])
- homvars = self._variables
- parameters = self._parameters
-
- if not self._homvar:
- return self
- else:
- homvar = self._homvar[0] # this will change for multihomogeneous polynomials
-
- homvars = list(homvars)
- dex = homvars.index(homvar)
- homvars.pop(dex)
- variables = spmatrix(homvars)
-
- polynomials = hompolys.subs({homvar:1})
-
- return PolynomialSystem(polynomials, variables, parameters)
-
- def equals(self, other, strict=True):
- """
- x.equals(y) <==> x == y
-
- A probability-1 algorithm to determine equality
- Optional arguments:
- strict -- if True, force each system to have the same variables,
- parameters, by name; otherwise, allow the same number
- of variables and parameters, but not necessarily share
- names. e.g.,
- `F = PolynomialSystem('x**2 - 1')
- G = PolynomialSystem('y**2 - 1')
- F.equals(G, strict=True) == False
- F.equals(G, strict=False) == True`
- """
- if not isinstance(other, PolynomialSystem):
- return False
- # shape test
- if self.shape != other.shape:
- return False
-
- svars = list(self._variables)
- ovars = list(other._variables)
- spars = list(self._parameters)
- opars = list(other._parameters)
- spoly = self._polynomials
- opoly = other._polynomials
- salls = svars + spars
- oalls = ovars + opars
-
- if strict and salls != oalls:
- return False
-
- from random import random as rand
- rsubs = []
- for vp in salls:
- try:
- real = rand()/rand()
- imag = rand()/rand()
- except ZeroDivisionError:
- return self == other
- rsubs.append(real + I*imag)
-
- ssubs = zip(salls, rsubs)
- osubs = zip(oalls, rsubs)
-
- res = spoly.subs(ssubs) - opoly.subs(osubs)
- return res.norm() < TOL
-
- def evalf(self, varpt, parpt=[]):
- """
- """
- from functools import reduce
-
- variables = list(self._variables)
- parameters = list(self._parameters)
- polynomials = self._polynomials
- if len(varpt) != len(variables):
- msg = "point {0} is not in the domain of {1}".format(varpt, self)
- raise ValueError(msg)
- elif len(parpt) != len(parameters):
- msg = "point {0} is not a valid parameter for {1}".format(parpt, self)
-
- if parpt:
- parpt = reduce(lambda x,y: x.cat(y), parpt)
-
- varsubs = dict(zip(variables, varpt) + zip(parameters, parpt))
-
- return AffinePoint(polynomials.evalf(subs=varsubs))
-
- def homogenize(self, homvar):
- """
- Homogenize the system
-
- If already homogeneous, return self
- """
- polynomials = [p.as_poly(domain='CC') for p in self._polynomials]
- variables = list(self._variables)
- parameters = list(self._parameters)
-
- if self._homvar:
- return self
-
- homvar = sympify(homvar)
- homvars = [homvar] + variables
- hompolys = [p.homogenize(homvar).as_expr() for p in polynomials]
- return PolynomialSystem(hompolys, homvars, parameters, homvar)
-
- def jacobian(self):
- """
- Returns the Jacobian, the polynomial system, and the variables,
- all as symbolic matrices
- """
- variables = self._variables
- polynomials = self._polynomials
- num_polynomials,num_variables = len(polynomials),len(variables)
- jac = zeros(num_polynomials,num_variables)
- for i in range(num_polynomials):
- for j in range(num_variables):
- jac[i,j] = polynomials[i].diff(variables[j])
-
- return jac,polynomials,variables
-
- def matmul(self, other):
- """
- x.matmul(y) <==> y*x
-
- (overriding __rmul__ gives strange behavior with spmatrix)
- """
- res_polys = list(other * self._polynomials)
- res = PolynomialSystem(res_polys)
-
- return res
-
- def fix_parameters(self, parsubs):
- """
- Substitute parsubs in for parameters
- """
- polynomials = self._polynomials
- parameters = self._parameters
- if type(parsubs) == dict:
- toreplace = parsubs.keys()
- replacements = parsubs.values()
- elif len(parsubs) > len(parameters):
- toreplace = parameters
- replacements = parsubs[:len(parameters)]
- elif len(parsubs) < len(parameters):
- toreplace = parameters[:len(parsubs)]
- replacements = parsubs
- else:
- toreplace = parameters
- replacements = parsubs
-
- tosub = dict()
- for p,q in zip(toreplace,replacements):
- if not scalar_num(q) and len(q) > 1:
- msg = 'cannot substitute {0}'.format(q)
- raise TypeError(msg)
- if isinstance(q, Point):
- q = q.coordinates[0]
- tosub[p] = q
- polynomials = polynomials.subs(tosub)
- parameters = set(parameters).difference(set(toreplace))
- if parameters:
- parameters = sorted([str(p) for p in parameters])
- parameters = sympify(parameters)
- self._parameters = parameters
- self._polynomials = polynomials
-
- def pop(self, index=-1):
- polynomials = list(self._polynomials)
- variables = self._variables
- parameters = self._parameters
-
- poly = polynomials.pop(index)
- polynomials = spmatrix(polynomials)
- if len(polynomials) > 0:
- free_sym = polynomials.free_symbols
- sympars = set(parameters).intersection(free_sym)
- symvars = set(variables).intersection(free_sym)
-
- varstr = sorted([str(v) for v in symvars])
- parstr = sorted([str(p) for p in sympars])
-
- variables = sympify(varstr)
- parameters = sympify(parstr)
- else:
- variables = []
- parameters = []
-
- self._polynomials = polynomials
- self._variables = spmatrix(variables)
- self._parameters = spmatrix(parameters)
-
- return poly
-
- def rank(self, tol=TOL):
- """
- Return a numeric value, the rank of the Jacobian at
- a 'generic' point.
- """
- from random import random as rand
- parameters = list(self._parameters)
- variables = list(self._variables)
- if parameters:
- allvars = variables + parameters
- else:
- allvars = variables
-
- varsubs = zeros(len(allvars), 1)
- # compute sufficiently generic complex points
- for i in range(len(varsubs)):
- # rand()/rand() can vary magnitude satisfactorily
- try:
- real = rand()/rand()
- imag = rand()/rand()
- except ZeroDivisionError:
- # try again
- return self.rank()
- varsubs[i] = real + I*imag
-
- jac = self.jacobian()[0]
- jac = jac.subs(zip(allvars, varsubs))
-
- # allow user to specify tolerance (what is 'zero')
- iszero = lambda x, tol=tol: True if abs(x) < tol else False
- return jac.rank(iszero)
-
- def solve(self, start_params=None, final_params=None, start=None, usebertini=True):
- """
- Solve the system. If non-square, return the NID
-
- If the system has parameters and you do not supply any parameters,
- perform ab initio run and return solutions along with start parameters.
- Otherwise if you supply parameters, just return the solutions.
- """
- polynomials = self._polynomials
- variables = self._variables
- parameters = self._parameters
-
- if usebertini:
- # parameter homotopy
- if parameters:
- if start_params and final_params:
- solve_run = naglib.bertini.BertiniRun(self,
- tracktype=naglib.bertini.BertiniRun.TZERODIM,
- config={'ParameterHomotopy':2},
- start_parameters=start_params,
- final_parameters=final_params,
- start=start)
- elif start_params or final_params:
- msg = "specify both start parameters and final parameters or neither"
- raise BertiniError(msg)
- else:
- solve_run = naglib.bertini.BertiniRun(self,
- naglib.bertini.BertiniRun.TZERODIM,
- config={'ParameterHomotopy':1})
- # numerical irreducible decomposition
- elif len(variables) > len(polynomials) or self.rank() < len(polynomials):
- solve_run = naglib.bertini.BertiniRun(self, naglib.bertini.BertiniRun.TPOSDIM)
- # isolated solutions
- else:
- solve_run = naglib.bertini.BertiniRun(self, naglib.bertini.BertiniRun.TZERODIM)
-
- return solve_run.run()
- else:
- msg = "nothing to use yet but Bertini"
- raise NotImplementedError(msg)
-
- def subs(self, *args, **kwargs):
- """
- Return a new PolynomialSystem with subs applied to
- each entry of 'polynomials'
-
- caution in using subs:
- this will destroy any parameter/homvar information in the system
- """
- polynomials = self._polynomials
- psubs = polynomials.subs(*args, **kwargs)
- ps = PolynomialSystem(psubs)
-
- return ps
-
- @property
- def polynomials(self):
- return self._polynomials
- @property
- def variables(self):
- return self._variables
- @property
- def parameters(self):
- return self._parameters
- @property
- def homvar(self):
- # TODO: change this for multihomogeneous systems
- if self._homvar:
- return self._homvar[0]
- else:
- return self._homvar
- @homvar.setter
- def homvar(self, h):
- if h is None:
- self._homvar = spmatrix()
- return
- h = sympify(h)
- if h not in self._variables:
- msg = "homogenizing variable {0} not found in list of variables".format(h)
- raise ValueError(msg)
-
- parameters = self._parameters
- polynomials = self._polynomials
- paramsubs = zip(parameters, [1 for p in parameters])
- for poly in polynomials:
- p = poly.subs(paramsubs)
- if p.is_number:
- deg = 0
- else:
- deg = p.as_poly(domain='CC').total_degree()
- # now check if polynomial is homogeneous
- terms = p.as_ordered_terms()
- for t in terms:
- if t.is_number and deg != 0:
- msg = "polynomial {0} is not homogeneous".format(p)
- raise NonHomogeneousException(msg)
- elif t.is_number:
- pass
- elif t.as_poly(domain='CC').total_degree() != deg:
- msg = "polynomial {0} is not homogeneous".format(p)
- raise NonHomogeneousException(msg)
-
- if h in self._variables:
- self._homvar = spmatrix([h])
- @property
- def degree(self):
- return self._degree
- @property
- def shape(self):
- m = len(self._polynomials)
- n = len(self._variables)
- return (m,n)
-
-class LinearSlice(NAGObject):
- """
- A linear system
-
- !!!Use this only for slicing!!!
- """
- def __init__(self, coeffs, variables, homvar=None):
- self._coeffs = spmatrix(coeffs)
- self._variables = spmatrix(variables)
- if homvar:
- homvar = sympify(homvar)
- if homvar not in variables:
- msg = "homogenizing variable {0} not in variables".format(homvar)
- raise ValueError(msg)
- else:
- self._homvar = homvar
- else:
- self._homvar = spmatrix()
-
- def __repr__(self):
- """
- x.__repr__() <==> repr(x)
- """
- coeffs = self._coeffs.n()
- variables = self._variables
- homvar = self._homvar
- repstr = 'LinearSlice({0},{1},{2})'.format(coeffs, variables, homvar)
-
- return repstr
-
- def __str__(self):
- """
- x.__str__() <==> str(x)
- """
- repstr = ''
- mat = self._coeffs * self._variables
- strmat = [str(row) for row in mat]
- maxlen = max([len(row) for row in strmat])
- for row in strmat:
- repstr += '[' + ' '*(maxlen-len(row)) + row + ']\n'
-
- return repstr
-
- def dehomogenize(self):
- """
- """
- homvar = self._homvar
- if not homvar:
- return self
-
- variables = list(self._variables)
- coeffs = self._coeffs.copy()
-
- dex = variables.index(homvar)
- variables.pop(dex)
- dehom_coeffs = coeffs.col(dex)
- coeffs.col_del(dex)
- m,n = coeffs.shape
- for i in range(m):
- coeffs[i,:] = coeffs[i,:]/dehom_coeffs[i]
-
- return LinearSlice(coeffs, variables)
-
- @property
- def codim(self):
- mat = self._coeffs
- m,n = mat.shape
- return n - m
- @property
- def coeffs(self):
- return self._coeffs
- @property
- def homvar(self):
- return self._homvar
- @property
- def mat(self):
- return self._coeffs * self._variables
- @property
- def rank(self, tol=TOL):
- iszero = lambda x, tol=tol: True if abs(x) < tol else False
- return self._coeffs.rank(iszerofunc=iszero)
- @property
- def shape(self):
- return self._coeffs.shape
- @property
- def variables(self):
- return self._variables
diff --git a/naglib/core/base.py b/naglib/core/base.py
deleted file mode 100644
index 0485d88..0000000
--- a/naglib/core/base.py
+++ /dev/null
@@ -1,482 +0,0 @@
-import numbers
-
-from naglib.exceptions import ExitSpaceError, AffineInfinityException
-from naglib.constants import TOL
-
-
-def is_scalar(z):
- """
- Determine if z is a scalar type for purposes of multiplication
- """
-
- return isinstance(z, numbers.Number)
-
-
-class NAGObject(object):
- """
- A meta class. Nothing here (yet)
- """
- pass
-
-
-class Point(NAGObject):
- """
- A point in affine or projective space
- """
-
- def __init__(self, coordinates):
- """
- Initialize the Point object
- """
- self._coordinates = Matrix(coordinates)
-
- def __add__(self, other):
- """
- x.__add__(y) <==> x + y
- """
- cls = self.__class__
- if not isinstance(other, cls):
- t = type(other)
- msg = "unsupported operand type(s) for +: '{0}' and '{1}'".format(cls, t)
- raise TypeError(msg)
-
- sco = self._coordinates
- oco = other._coordinates
-
- if len(sco) != len(oco):
- msg = "dimension mismatch"
- raise ShapeError(msg)
-
- return cls(list(sco + oco))
-
- def __sub__(self, other):
- """
- x.__sub__(y) <==> x - y
- """
- cls = self.__class__
- if not isinstance(other, cls):
- t = type(other)
- msg = "unsupported operand type(s) for -: '{0}' and '{1}'".format(cls, t)
- raise TypeError(msg)
-
- return self + -other
-
- def __neg__(self):
- """
- x.__neg__() <==> -x
- """
- cls = self.__class__
- coordinates = self._coordinates
- return cls(list(-coordinates))
-
- def __mul__(self, other):
- """
- x.__mul__(y) <==> x*y
- """
- cls = self.__class__
- if not is_scalar(other):
- t = type(other)
- msg = "unsupported operand type(s) for *: '{0}' and '{1}'".format(cls, t)
- raise TypeError(msg)
- else:
- coordinates = self._coordinates
- return cls(other * coordinates)
-
- def __rmul__(self, other):
- """
- x.__rmul__(y) <==> y*x
- """
- cls = self.__class__
- if not is_scalar(other):
- t = type(other)
- msg = "unsupported operand type(s) for *: '{0}' and '{1}'".format(t, cls)
- raise TypeError(msg)
- else:
- return self * other
-
- def __div__(self, other):
- """
- x.__div__(y) <==> x/y
- """
- return self.__truediv__(other)
-
- def __truediv__(self, other):
- """
- x.__truediv__(y) <==> x/y
- """
- cls = self.__class__
- if not is_scalar(other):
- t = type(other)
- msg = "unsupported operand type(s) for /: '{0}' and '{1}'".format(cls, t)
- raise TypeError(msg)
- else:
- if other == 0:
- msg = "division by zero"
- raise ZeroDivisionError(msg)
- coordinates = self._coordinates
- return cls((1.0/other) * coordinates)
-
- def __eq__(self, other):
- """
- x.__eq__(y) <==> x == y
- """
- cls = self.__class__
- if not isinstance(other, cls):
- return False
-
- sco = self._coordinates
- oco = other._coordinates
-
- return (sco == oco)
-
- def __len__(self):
- """
- x.__len__() <==> len(x)
- """
- coordinates = self._coordinates
- return len(coordinates)
-
- def __getitem__(self, key):
- """
- x.__getitem__(y) <==> x[y]
- """
- coordinates = self._coordinates
- return coordinates[key]
-
- def __setitem__(self, key, value):
- """
- x.__setitem__(y, z) <==> x[y] = z
- """
- if not is_scalar(value):
- msg = "must assign a number"
- raise TypeError(msg)
-
- coordinates = self._coordinates
- coordinates[key] = sympify(value)
-
- def __setslice__(self, i, j, sequence):
- """
- x.__setslice__(i,j,sequence) <==> x[i:j] = sequence
- """
- coordinates = self._coordinates
-
- sequence = sympify(list(sequence))
- for s in sequence:
- if not is_scalar(s):
- msg = "must assign a number"
- raise TypeError(msg)
-
- cocopy = coordinates[:]
- cocopy[i:j] = sequence
- self._coordinates = Matrix(cocopy)
-
- def cat(self, other):
- """
- concatenate other onto self
- """
- cls = self.__class__
- if not isinstance(other, cls):
- t = type(other)
- msg = "I don't know how to concatenate type {0} to type {1}".format(t, cls)
- raise TypeError(msg)
- scoords = list(self._coordinates)
- ocoords = list(other._coordinates)
-
- return cls(scoords + ocoords)
-
- def float(self, prec=None):
- cls = self.__class__
- coordinates = self._coordinates
- newcoords = []
- for c in coordinates:
- real,imag = c.as_real_imag()
- if prec:
- real = sympy.Float(real, prec)
- imag = sympy.Float(imag, prec)
- else:
- real = sympy.Float(real)
- imag = sympy.Float(imag)
- newcoords.append(real + sympy.I*imag)
-
- return cls(newcoords)
-
- def insert(self, index, item):
- if not is_scalar(item):
- msg = "only takes scalar number types"
- raise TypeError(msg)
- coordinates = list(self._coordinates)
- coordinates.insert(index, item)
- self._coordinates = Matrix(coordinates)
-
- def is_zero(self, tol=TOL*10):
- coordinates = self._coordinates
- summa = sum([abs(c)**2 for c in coordinates])**0.5
- return summa < tol
-
- def normalized(self):
- """
- Returns the normalized version of self
- """
- coordinates = self._coordinates
- return self.__class__(coordinates.normalized())
-
- def pop(self, index=-1):
- coordinates = list(self._coordinates)
- popped = coordinates.pop(index)
- self._coordinates = Matrix(coordinates)
-
- return popped
-
- def rational(self):
- """
- Returns a rational approximation of self
- """
- cls = self.__class__
- coordinates = self._coordinates
- newcoords = []
- for c in coordinates:
- real,imag = c.as_real_imag()
- real = Rational(real)
- imag = Rational(imag)
- newcoords.append(real + sympy.I*imag)
-
- return cls(newcoords)
-
- def is_real(self, tol=1e-13):
- coordinates = self._coordinates
- return coordinates.as_real_imag()[1].norm() < tol
-
- @property
- def coordinates(self):
- return self._coordinates
-
-
-class AffinePoint(Point):
- """
- Point object living in affine space
- """
- def __init__(self, coordinates):
- super(AffinePoint, self).__init__(coordinates)
-
- def __repr__(self):
- coordinates = [str(c.n()) for c in self._coordinates]
- repstr = 'AffinePoint(['
- if len(coordinates) > 6:
- repstr += ', '.join(coordinates[:3] + ['...'] + coordinates[-3:]) + '])'
- else:
- repstr = 'AffinePoint({0})'.format(', '.join(coordinates))
-
- return repstr
-
- def __str__(self):
- """
- x.__str__ <==> str(x)
- """
- coordinates = self._coordinates
- repstr = '[' + ', '.join([str(c) for c in coordinates]) + ']'
-
- return repstr
-
- def __abs__(self):
- """
- x.__abs__ <==> abs(x)
- """
- coordinates = self._coordinates
- return coordinates.norm()
-
- def homogenize(self):
- """
- """
- homcoordinates = [1] + list(self._coordinates)
-
- return ProjectivePoint(homcoordinates)
-
- def norm(self, ord=None):
- """
- Return the norm of AffinePoint
- Acceptable values:
- None <==> 2-norm
- inf <==> max(abs(x))
- -inf <==> min(abs(x))
- n <==> sum(abs(x)**n)**(1./n)
- """
- coordinates = self._coordinates
- return coordinates.norm(ord)
-
- @property
- def dim(self):
- return len(self._coordinates)
-
-class ProjectivePoint(Point):
- """
- Point object living in affine space
- """
- def __init__(self, coordinates, tol=TOL*10):
- super(ProjectivePoint, self).__init__(coordinates)
-
- if self.is_zero(tol):
- corstr = '[' + ' : '.join([str(c) for c in self._coordinates]) + ']'
- msg = "{0} is not in projective space".format(corstr)
- raise ExitSpaceError(msg)
- self._dim = len(self._coordinates) - 1
- self._tol = tol
-
- def __repr__(self):
- coordinates = [str(c.n()) for c in self._coordinates]
- repstr = 'ProjectivePoint(['
- if len(coordinates) > 6:
- repstr += ', '.join(coordinates[:3] + ['...'] + coordinates[-3:]) + '])'
- else:
- repstr = 'ProjectivePoint({0})'.format(', '.join(coordinates))
-
- return repstr
-
- def __str__(self):
- """
- x.__str__ <==> str(x)
- """
- coordinates = self._coordinates
- repstr = '[' + ' : '.join([str(c) for c in coordinates]) + ']'
-
- return repstr
-
- def __add__(self, other):
- """
- x.__add__(y) <==> x + y
- """
- res = super(ProjectivePoint, self).__add__(other)
- if res.is_zero(self._tol):
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- return res
-
- def __sub__(self, other):
- """
- x.__sub__(y) <==> x - y
- """
- res = super(ProjectivePoint, self).__sub__(other)
- if res.is_zero(self._tol):
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- return res
-
- def __mul__(self, other):
- """
- x.__mul__(y) <==> x*y
- """
- res = super(ProjectivePoint, self).__mul__(other)
- if res.is_zero(self._tol):
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- return res
-
- def __rmul__(self, other):
- """
- x.__rmul__(y) <==> y*x
- """
- res = super(ProjectivePoint, self).__rmul__(other)
- if res.is_zero(self._tol):
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- def __div__(self, other):
- """
- x.__div__(y) <==> x/y
- """
- res = super(ProjectivePoint, self).__div__(other)
- if res.is_zero(self._tol):
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- return res
-
- def __truediv__(self, other):
- """
- x.__truediv__(y) <==> x/y
- """
- res = super(ProjectivePoint, self).__truediv__(other)
- if res.is_zero(self._tol):
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- return res
-
- def __eq__(self, other):
- """
- x.__eq__(u=y) <==> x == y
- """
- if not isinstance(other, ProjectivePoint):
- return False
-
- # (x0, ..., xn) == (y0, ..., yn) if there exists c s.t.
- # (x0, ..., xn) == c(y0, ..., yn)
- sho = self.canonical()
- oho = other.canonical()
- sco = sho._coordinates
- oco = oho._coordinates
-
- return sco == oco
-
- def __setitem__(self, key, value):
- """
- x.__setitem__(y, z) <==> x[y] = z
- """
- coordinates = self._coordinates.copy()
- super(ProjectivePoint, self).__setitem__(key, value)
- if self.is_zero(self._tol):
- self._coordinates = coordinates
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- def __setslice__(self, i, j, sequence):
- """
- x.__setitem__(y, z) <==> x[y] = z
- """
- coordinates = self._coordinates.copy()
- super(ProjectivePoint, self).__setslice__(i, j, sequence)
- if self.is_zero(self._tol):
- self._coordinates = coordinates
- msg = 'you have left projective space'
- raise ExitSpaceError(msg)
-
- def at_infinity(self, tol=TOL):
- coordinates = self._coordinates
- c0 = coordinates[0]
- div_coord = [c0/c for c in coordinates[1:]]
- return sum([abs(c)**2 for c in div_coord])**(0.5) < tol
-
- def canonical(self):
- """
- Return ProjectivePoint with coordinates rescaled
- """
- coordinates = self._coordinates
- nz = 0
- while abs(coordinates[nz]) < TOL and nz < len(coordinates):
- nz += 1
- c1 = coordinates[nz]
-
- return ProjectivePoint(coordinates/c1)
-
- def dehomogenize(self):
- """
- Return Affine Point, if not at at infinity
- """
- if not self.at_infinity():
- coordinates = self._coordinates
- return AffinePoint([c/coordinates[0] for c in coordinates[1:]])
- else:
- msg = "cannot create affine point from {0}; point is at infinity".format(self)
- raise AffineInfinityException(msg)
-
- @property
- def dim(self):
- return len(self._coordinates)-1
- @property
- def tol(self):
- return self._tol
- @tol.setter
- def tol(self, t):
- self._tol = t
diff --git a/naglib/core/geometry.py b/naglib/core/geometry.py
deleted file mode 100644
index 1a1eb69..0000000
--- a/naglib/core/geometry.py
+++ /dev/null
@@ -1,208 +0,0 @@
-from __future__ import print_function
-
-from sympy import Matrix
-
-from naglib.bertini.sysutils import BertiniRun
-from naglib.exceptions import BertiniError
-from naglib.core.base import NAGObject
-
-class IrreducibleComponent(NAGObject):
- """
- An irreducible component of an algebraic set
- """
- def __init__(self, witness_set, codim, component_id, **kwargs):
- """
- Initialize the IrreducibleComponent object.
-
- Keyword arguments:
- witness_set -- WitnessSet, the witness set describing this component
- codim -- int, the codimension of the component
- component_id -- int, the component number for this dimension
-
- Optional keyword arguments:
- """
- self._witness_set = witness_set
- self._codim = codim
- self._component_id = component_id
- self._degree = len(witness_set.witness_points)
-
- # optional keyword arguments
- kkeys = kwargs.keys()
-
- if 'randomization_matrix' in kkeys:
- self._randomization_matrix = kwargs['randomization_matrix']
- else:
- self._randomization_matrix = Matrix([])
-
- if 'homogenization_matrix' in kkeys:
- self._homogenization_matrix = kwargs['homogenization_matrix']
- else:
- self._homogenization_matrix = Matrix([])
-
- if 'homogenization_vector' in kkeys:
- self._homogenization_vector = kwargs['homogenization_vector']
- else:
- self._homogenization_vector = Matrix([])
-
- if 'homogenization_variable' in kkeys:
- self._homogenization_variable = kwargs['homogenization_variable']
- else:
- self._homogenization_variable = None
-
- if 'patch_coefficients' in kkeys:
- self._patch_coefficients = kwargs['patch_coefficients']
- else:
- self._patch_coefficients = Matrix([])
-
- def __str__(self):
- """
- x.__str__() <==> str(x)
- """
- codim = self._codim
- cid = self._component_id
- deg = self._degree
- return '{0}-dimensional irreducible component ({2}) of degree {1}'.format(codim,deg,cid)
-
- def __repr__(self):
- """
- x.__repr__() <==> repr(x)
- """
- codim = self._codim
- cid = self._component_id
- wst = self._witness_set
- repstr = 'IrreducibleComponent({0},{1},{2})'.format(repr(wst),codim,cid)
- return repstr
-
- def __eq__(self, other):
- """
- x.__eq__(y) <==> x == y
- """
- if type(other) != IrreducibleComponent:
- return False
-
- sp = self.sample(1)
- op = other.sample(1)
-
- sco = self.contains(op)
- ocs = other.contains(sp)
-
- return sco and ocs
-
- def _construct_witness_data(self):
- codim = self._codim
- wpoints = self.witness_set.witness_points
- hslice = self.witness_set.homogeneous_slice.coeffs
- if not hslice:
- hslice = self.witness_set.linear_slice.coeffs
- homogenization_matrix = self._homogenization_matrix
- homogenization_variable = self._homogenization_variable
- homogenization_vector = self._homogenization_vector
- patch_coefficients = self._patch_coefficients
- randomization_matrix = self._randomization_matrix
-
- wd = {
- 'codim':codim,
- 'points':[],
- 'A':randomization_matrix,
- 'W':homogenization_matrix,
- 'homVarConst':homogenization_variable,
- 'H':homogenization_vector,
- 'p':patch_coefficients,
- 'slice':hslice
- }
-
- for p in wpoints:
- if p.homogeneous_coordinates:
- coordinates = p.homogeneous_coordinates
- else:
- coordinates = p.coordinates
- wd['points'].append({
- 'precision':p.precision,
- 'coordinates':coordinates,
- 'last approximation':p.last_approximation.coordinates,
- 'condition number':p.condition_number,
- 'corank':p.corank,
- 'smallest nonzero':p.smallest_nonzero,
- 'largest zero':p.largest_zero,
- 'type':p.point_type,
- 'multiplicity':p.multiplicity,
- 'component number':0,
- 'deflations':p.deflations
- })
-
- return [wd]
-
- def contains(self, other):
- """
- Return True if self contains other
- """
- if type(other) not in (list, tuple):
- msg = "cannot understand data type"
- raise TypeError(msg)
-
- system = self._witness_set.system
- test_run = BertiniRun(system,
- tracktype=BertiniRun.TMEMTEST,
- component=self,
- start=other)
- return test_run.run()
-
- def sample(self, numpoints=1, usebertini=True):
- """
- Sample points from self
- """
- if numpoints < 1:
- msg = "sample at least one point"
- raise BertiniError(msg)
- system = self.witness_set.system
-
- points = None
- if usebertini:
- sample_run = BertiniRun(system, BertiniRun.TSAMPLE, sample=numpoints, component=self)
- points = sample_run.run()
- else:
- msg = "nothing to use yet but Bertini"
- raise NotImplementedError(msg)
-
- return points
-
- @property
- def codim(self):
- return self._codim
- @property
- def component_id(self):
- return self._component_id
- @property
- def degree(self):
- return self._degree
- @property
- def dim(self):
- variables = self.system.variables
- return len(variables) - self._codim
- @property
- def homogenization_matrix(self):
- return self._homogenization_matrix
- @property
- def homogenization_variable(self):
- return self._homogenization_variable
- @property
- def homogenization_vector(self):
- return self._homogenization_vector
- @property
- def is_projective(self):
- return not not self._homogenization_variable
- @property
- def patch_coefficients(self):
- return self._patch_coefficients
- @property
- def randomization_matrix(self):
- return self._randomization_matrix
- @property
- def system(self):
- return self._witness_set.system
- @property
- def witness_data(self):
- return self._witness_set._witness_data
- @property
- def witness_set(self):
- return self._witness_set
\ No newline at end of file
diff --git a/naglib/core/witnessdata.py b/naglib/core/witnessdata.py
deleted file mode 100644
index 80bc1f1..0000000
--- a/naglib/core/witnessdata.py
+++ /dev/null
@@ -1,364 +0,0 @@
-from sympy import I, Float, Rational, Matrix
-
-from naglib.exceptions import WitnessDataException
-from naglib.core.base import NAGObject, Point, AffinePoint, ProjectivePoint
-
-
-class WitnessPoint(Point):
- """
- A single witness point for an algebraic set
- """
- def __init__(self, coordinates, component_id, is_projective=False, **kwargs):
- """
- Initialize the WitnessPoint object.
-
- Keyword arguments:
- point -- AffinePoint or ProjectivePoint
- component_id -- int, the id of the component to which self belongs
- """
- super(WitnessPoint, self).__init__(coordinates)
- self._component_id = component_id
- self._is_projective = is_projective
- if isinstance(coordinates, AffinePoint):
- self._is_projective = False
- elif isinstance(coordinates, ProjectivePoint):
- self._is_projective = True
-
- kkeys = kwargs.keys()
-
- if 'corank' in kkeys:
- self._corank = kwargs['corank']
- else:
- self._corank = -1
-
- if 'condition_number' in kkeys:
- self._condition_number = kwargs['condition_number']
- else:
- self._condition_number = 0
-
- if 'smallest_nonzero' in kkeys:
- self._smallest_nonzero = kwargs['smallest_nonzero']
- else:
- self._smallest_nonzero = 0
-
- if 'largest_zero' in kkeys:
- self._largest_zero = kwargs['largest_zero']
- else:
- self._largest_zero = 0
-
- if 'point_type' in kkeys:
- self._point_type = kwargs['point_type']
- else:
- self._point_type = 0
-
- if 'multiplicity' in kkeys:
- self._multiplicity = kwargs['multiplicity']
- else:
- self._multiplicity = 1
-
- if 'deflations' in kkeys:
- self._deflations = kwargs['deflations']
- else:
- self._deflations = 0
-
- if 'precision' in kkeys:
- self._precision = kwargs['precision']
- else:
- self._precision = 0
-
- if 'last_approximation' in kkeys:
- self._last_approximation = kwargs['last_approximation']
- else:
- self._last_approximation = Matrix([])
-
- if 'homogeneous_coordinates' in kkeys:
- self._homogeneous_coordinates = kwargs['homogeneous_coordinates']
- else:
- self._homogeneous_coordinates = Matrix([])
-
- # TODO: sanity check projective point
-
- def __repr__(self):
- """
- x.__repr__() <==> repr(x)
- """
- coordinates = [str(c.n()) for c in self._coordinates]
- component_id = self._component_id
- is_projective = self._is_projective
-
- if is_projective:
- repstr = 'ProjectivePoint(['
- if len(coordinates) > 6:
- repstr += ', '.join(coordinates[:3] + ['...'] + coordinates[-3:]) + '])'
- else:
- repstr = 'ProjectivePoint({0})'.format(', '.join(coordinates))
- else:
- repstr = 'AffinePoint(['
- if len(coordinates) > 6:
- repstr += ', '.join(coordinates[:3] + ['...'] + coordinates[-3:]) + '])'
- else:
- repstr = 'AffinePoint({0})'.format(', '.join(coordinates))
-
- repstr = 'WitnessPoint({0},{1})'.format(repstr, component_id)
-
- return repstr
-
- def __str__(self):
- """
- x.__str__() <==> str(x)
- """
- coordinates = self._coordinates
- is_projective = self._is_projective
-
- if is_projective:
- repstr = '[' + ' : '.join([str(c) for c in coordinates]) + ']'
- else:
- repstr = '[' + ', '.join([str(c) for c in coordinates]) + ']'
-
- return repstr
-
- def as_point(self):
- coordinates = self._coordinates
- is_projective = self._is_projective
- if is_projective:
- return ProjectivePoint(coordinates)
- else:
- return AffinePoint(coordinates)
-
- def dehomogenize(self):
- """
- Dehomogenize the witness point
-
- Returns a new WitnessPoint object
- """
- cls = self.__class__
- component_id = self._component_id
- coordinates = self._coordinates
- is_projective = self._is_projective
-
- if is_projective:
- point = ProjectivePoint(coordinates)
- else:
- point = AffinePoint(coordinates)
-
- deh = cls(point, component_id)
- deh._is_projective = self._is_projective
- deh._condition_number = self._condition_number
- deh._corank = self._corank
- deh._deflations = self._deflations
- deh._last_approximation = self._last_approximation
- deh._largest_zero = self._largest_zero
- deh._multiplicity = self._multiplicity
- deh._point_type = self._point_type
- deh._precision = self._precision
- deh._smallest_nonzero = self._smallest_nonzero
-
- return deh
-
- def float(self, prec=None):
- cls = self.__class__
- component_id = self._component_id
- coordinates = self._coordinates
- newcoords = []
- for c in coordinates:
- real,imag = c.as_real_imag()
- if prec:
- real = Float(real, prec)
- imag = Float(imag, prec)
- else:
- real = Float(real)
- imag = Float(imag)
- newcoords.append(real + I*imag)
- flo = cls(coordinates, component_id)
-
- flo._is_projective = self._is_projective
- flo._condition_number = self._condition_number
- flo._corank = self._corank
- flo._deflations = self._deflations
- flo._last_approximation = self._last_approximation.float()
- flo._largest_zero = self._largest_zero
- flo._multiplicity = self._multiplicity
- flo._point_type = self._point_type
- if prec and prec <= self._precision:
- flo._precision = prec
- else:
- flo._precision = self._precision
- flo._smallest_nonzero = self._smallest_nonzero
-
- return flo
-
- def rational(self):
- """
- Returns a rational approximation of self
- """
- cls = self.__class__
- component_id = self._component_id
- coordinates = self._coordinates
- newcoords = []
- for c in coordinates:
- real,imag = c.as_real_imag()
- real = Rational(real)
- imag = Rational(imag)
- newcoords.append(real + I*imag)
- rat = cls(newcoords, component_id)
-
- rat._is_projective = self._is_projective
- rat._condition_number = self._condition_number
- rat._corank = self._corank
- rat._deflations = self._deflations
- rat._last_approximation = self._last_approximation
- rat._largest_zero = self._largest_zero
- rat._multiplicity = self._multiplicity
- rat._point_type = self._point_type
- rat._precision = self._precision
- rat._smallest_nonzero = self._smallest_nonzero
-
- return rat
-
- @property
- def condition_number(self):
- """
- The condition number of the Jacobian at this point
- """
- return self._condition_number
-
- @property
- def corank(self):
- """
- The corank of the Jacobian at this point
- """
- return self._corank
-
- @property
- def component_id(self):
- return self._component_id
-
- @property
- def deflations(self):
- """
- The number of deflations this point required
- """
- return self._deflations
-
- @property
- def homogeneous_coordinates(self):
- """
- The homogeneous coordinates of the witness point
- """
- return self._homogeneous_coordinates
-
- @property
- def last_approximation(self):
- coordinates = self._last_approximation
- is_projective = self._is_projective
- if is_projective:
- return ProjectivePoint(coordinates)
- else:
- return AffinePoint(coordinates)
-
- @property
- def largest_zero(self):
- """
- The largest `zero' singular value of the Jacobian at this point
- """
- return self._largest_zero
-
- @property
- def multiplicity(self):
- """
- The multiplicity of this point with respect to the system
- """
- return self._multiplicity
-
- @property
- def point_type(self):
- return self._point_type
-
- @property
- def precision(self):
- """
- The numerical precision required by this point
- """
- return self._precision
-
- @property
- def smallest_nonzero(self):
- """
- The smallest nonzero singular value of the Jacobian at this point
- """
- return self._smallest_nonzero
-
-class WitnessSet(NAGObject):
- """
- A witness set for a component
- """
- def __init__(self, system, lslice, witness_points, witness_data, **kwargs):
- """Initialize the WitnessSet
-
- Keyword arguments:
- system -- PolynomialSystem, system on which all the points vanish
- slice -- LinearSystem, system defining a generic linear space
- witness_points -- iterable of WitnessPoint objects, witness point set, V(f) \cap V(L)
- """
- self._system = system
- self._slice = lslice
- self._witness_data = witness_data
- try:
- self._witness_points = list(witness_points)
- except TypeError:
- self._witness_points = [witness_points]
-
- wp = self._witness_points[0]
- self._component_id = wp._component_id
- for w in self._witness_points:
- if w._component_id != self._component_id:
- msg = 'WitnessPoint {0} and WitnessPoint {1} do not lie on the same component'.format(wp, w)
- raise WitnessDataException(msg)
-
- kkeys = kwargs.keys()
-
- if 'homogeneous_slice' in kkeys:
- self._homogeneous_slice = kwargs['homogeneous_slice']
- else:
- self._homogeneous_slice = None
-
- def __repr__(self):
- """
- x.__repr__() <==> repr(x)
- """
- sy = self._system
- sl = self._slice
- wp = self._witness_points
- repstr = 'WitnessSet({0},{1},{2})'.format(repr(sy), repr(sl), repr(wp))
-
- return repstr
-
- def __str__(self):
- """
- x.__str__() <==> str(x)
- """
- wp = self._witness_points
- repstr = '{' + ', '.join([str(p) for p in wp]) + '}'
-
- return repstr
-
-
- @property
- def homogeneous_slice(self):
- return self._homogeneous_slice
-
- @property
- def linear_slice(self):
- return self._slice
-
- @property
- def system(self):
- return self._system
-
- @property
- def witness_data(self):
- return self._witness_data
-
- @property
- def witness_points(self):
- return self._witness_points
\ No newline at end of file
diff --git a/naglib/environment.yml b/naglib/environment.yml
deleted file mode 100644
index 51f9487..0000000
--- a/naglib/environment.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: naglib
-channels:
-- defaults
-- conda-forge
-dependencies:
-- python=3.*
-- numpy
-- scipy
-- sympy
diff --git a/naglib/misc.py b/naglib/misc.py
deleted file mode 100644
index 722ce34..0000000
--- a/naglib/misc.py
+++ /dev/null
@@ -1,11 +0,0 @@
-def dps(s):
- #return max(DPS, len(s))
- s = str(s) if not isinstance(s, str) else s
- return len(s)
-
-
-def striplines(lines, nonempty=True):
- if nonempty:
- return [l.strip() for l in lines if l != '\n']
- else:
- return [l.strip() for l in lines]
\ No newline at end of file
diff --git a/naglib/system.py b/naglib/system.py
deleted file mode 100644
index ca402af..0000000
--- a/naglib/system.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import multiprocessing
-import subprocess
-import sys
-
-def __os():
- if sys.platform.startswith("win"):
- return "WINDOWS"
- elif sys.platform.startswith("cygwin"):
- return "CYGWIN"
- elif sys.platform.startswith("linux"):
- return "LINUX"
- elif sys.platform.startswith("darwin"):
- return "OSX"
-
-def __which(exe):
- platform = __os()
- if platform == "WINDOWS":
- cmd = "where.exe"
- else:
- cmd = "which"
-
- try:
- path = subprocess.check_output([cmd, exe], universal_newlines=True).strip()
- except subprocess.CalledProcessError:
- path = ""
-
- return path
-
-def proc_err_output(output):
- lines = output.split("\n")
- idx = None
- for l in lines:
- if l.startswith("ERROR"):
- idx = lines.index(l)
- if idx is None:
- return output
- else:
- errline = lines[idx]
- # strip "ERROR: "
- lines[idx] = errline[errline.index(" ")+1:]
- # strip "Bertini will now exit due to this error"
- return "\n".join(lines[idx:-1])
-
-BERTINI = __which("bertini")
-MPIRUN = __which("mpirun")
-PCOUNT = multiprocessing.cpu_count()
diff --git a/requirements.txt b/requirements.txt
index 90c0d66..5d17483 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,4 @@
-certifi==2019.3.9
-fastcache==1.1.0
-mkl-fft==1.0.12
-mkl-random==1.0.2
-mpmath==1.1.0
-numpy==1.16.4
-wincertstore==0.2
+mpmath
+numpy
+pytest
+scipy
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..c419344
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,12 @@
+from setuptools import setup
+
+setup(
+ name='bertini',
+ version='0.1.0',
+ packages=['bertini'],
+ url='https://github.com/aliddell/python-bertini',
+ license='BSD',
+ author='Alan',
+ author_email='alan d.t c d.t liddell @t gmail d.t com',
+ description='Library for numerical algebraic geometry, mostly a wrapper for Bertini classic'
+)
diff --git a/test/.coveragerc b/test/.coveragerc
new file mode 100644
index 0000000..87937af
--- /dev/null
+++ b/test/.coveragerc
@@ -0,0 +1,11 @@
+[report]
+exclude_lines =
+ pragma: no cover
+ def __repr__
+ if self.debug:
+ if settings.DEBUG
+ raise AssertionError
+ raise NotImplementedError
+ if 0:
+ if __name__ == .__main__.:
+show_missing = true
diff --git a/test/conftest.py b/test/conftest.py
new file mode 100644
index 0000000..b7cd8d4
--- /dev/null
+++ b/test/conftest.py
@@ -0,0 +1,9 @@
+import os.path as op
+import sys
+
+print(__file__)
+BASEDIR = op.abspath(op.join(op.dirname(__file__), ".."))
+sys.path.insert(0, BASEDIR)
+
+ZERO_DIM_BASE = op.join(BASEDIR, "test", "data", "zero_dim")
+POS_DIM_BASE = op.join(BASEDIR, "test", "data", "pos_dim")
diff --git a/test/data/Bertini_examples/AppendixQuickStart/._.DS_Store b/test/data/Bertini_examples/AppendixQuickStart/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/AppendixQuickStart/._.DS_Store differ
diff --git a/test/data/Bertini_examples/AppendixQuickStart/FirstRun.input b/test/data/Bertini_examples/AppendixQuickStart/FirstRun.input
new file mode 100644
index 0000000..525ab1d
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/FirstRun.input
@@ -0,0 +1,6 @@
+ variable_group x,y;
+ function f,g;
+
+ f = x^2 - 1;
+ g = y^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/Homogeneous.input b/test/data/Bertini_examples/AppendixQuickStart/Homogeneous.input
new file mode 100644
index 0000000..91951cf
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/Homogeneous.input
@@ -0,0 +1,6 @@
+% Homogeneous.input
+ function f;
+ hom_variable_group x,y;
+
+ f = x^2 - y^2;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/MoreAccuracy.input b/test/data/Bertini_examples/AppendixQuickStart/MoreAccuracy.input
new file mode 100644
index 0000000..58bf627
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/MoreAccuracy.input
@@ -0,0 +1,10 @@
+% MoreAccuracy.input
+CONFIG
+ FinalTol:1e-20;
+END;
+INPUT
+ function f;
+ variable_group x;
+
+ f = x^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/ParameterHomotopy.input b/test/data/Bertini_examples/AppendixQuickStart/ParameterHomotopy.input
new file mode 100644
index 0000000..26bca68
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/ParameterHomotopy.input
@@ -0,0 +1,11 @@
+% ParameterHomotopy.input
+CONFIG
+ ParameterHomotopy:1;
+END;
+INPUT
+ variable_group x;
+ function f;
+ parameter s;
+
+ f = x^2-s;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/Sqrt1.input b/test/data/Bertini_examples/AppendixQuickStart/Sqrt1.input
new file mode 100644
index 0000000..d893dd0
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/Sqrt1.input
@@ -0,0 +1,6 @@
+% Sqrt1.input
+ function f;
+ variable_group x;
+
+ f = x^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/Subfunctions.input b/test/data/Bertini_examples/AppendixQuickStart/Subfunctions.input
new file mode 100644
index 0000000..6347c1f
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/Subfunctions.input
@@ -0,0 +1,12 @@
+% Subfunctions.input
+ variable_group x,y,z;
+ function f1,f2,f3;
+
+ S = x^2+y^2+z^2-1;
+ T = y-x^2;
+ U = x*y-z;
+
+ f1 = S*T*(x-2);
+ f2 = S*U*(y-2);
+ f3 = S*T*U*(z-2);
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/TwistedCubic.input b/test/data/Bertini_examples/AppendixQuickStart/TwistedCubic.input
new file mode 100644
index 0000000..acdc915
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/TwistedCubic.input
@@ -0,0 +1,11 @@
+% TwistedCubic.input
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ variable_group x,y,z;
+ function f1,f2;
+
+ f1 = x^2-y;
+ f2 = x^3-z;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/TwoGroups.input b/test/data/Bertini_examples/AppendixQuickStart/TwoGroups.input
new file mode 100644
index 0000000..7f734e4
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/TwoGroups.input
@@ -0,0 +1,8 @@
+% TwoGroups.input
+ variable_group z1;
+ variable_group z2;
+ function f1,f2;
+
+ f1 = (29/16)*z1^3 - 2*z1*z2;
+ f2 = z2 - z1^2;
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy.start b/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy.start
new file mode 100644
index 0000000..f89f545
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy.start
@@ -0,0 +1,5 @@
+2
+
+-1.0 0.0
+
+1.0 0.0
diff --git a/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy_Affine.input b/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy_Affine.input
new file mode 100644
index 0000000..58f5f7a
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy_Affine.input
@@ -0,0 +1,17 @@
+% UserHomotopy_Affine.input
+CONFIG
+ UserHomotopy:1;
+END;
+INPUT
+ variable x;
+ function f;
+ pathvariable t;
+ parameter s;
+ constant gamma;
+
+ gamma = 0.8 - 1.2*I;
+ s = t;
+
+ f = (x^2-1)*gamma*s + (x^2)*(1-s);
+ % Note: t does not explicitly appear in f
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy_Projective.input b/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy_Projective.input
new file mode 100644
index 0000000..1fa7cae
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/UserHomotopy_Projective.input
@@ -0,0 +1,17 @@
+% UserHomotopy_Projective.input
+CONFIG
+ UserHomotopy:2;
+END;
+INPUT
+ variable_group x;
+ function f;
+ pathvariable t;
+ parameter s;
+ constant gamma;
+
+ gamma = 0.8 - 1.2*I;
+ s = t;
+
+ f = (x^2-1)*gamma*s + (x^2)*(1-s);
+ % Note: t does not explicitly appear in f
+END;
diff --git a/test/data/Bertini_examples/AppendixQuickStart/final_parameters b/test/data/Bertini_examples/AppendixQuickStart/final_parameters
new file mode 100644
index 0000000..22825f5
--- /dev/null
+++ b/test/data/Bertini_examples/AppendixQuickStart/final_parameters
@@ -0,0 +1,3 @@
+1
+
+2 0
diff --git a/test/data/Bertini_examples/Chap11AdvancedPosDim/._.DS_Store b/test/data/Bertini_examples/Chap11AdvancedPosDim/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap11AdvancedPosDim/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap11AdvancedPosDim/Deflation.input b/test/data/Bertini_examples/Chap11AdvancedPosDim/Deflation.input
new file mode 100644
index 0000000..9cb106f
--- /dev/null
+++ b/test/data/Bertini_examples/Chap11AdvancedPosDim/Deflation.input
@@ -0,0 +1,11 @@
+% Deflation.input
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ variable_group x,y;
+ function cylinder,sphere;
+
+ cylinder = x^2 + y^2 - 1;
+ sphere = x^2 + y^2 + z^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap11AdvancedPosDim/LineCircle.input b/test/data/Bertini_examples/Chap11AdvancedPosDim/LineCircle.input
new file mode 100644
index 0000000..25d34db
--- /dev/null
+++ b/test/data/Bertini_examples/Chap11AdvancedPosDim/LineCircle.input
@@ -0,0 +1,10 @@
+% LineCircle.input
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ function f;
+ variable_group x,y;
+
+ f = (x - y)*(x^2 + y^2 - 1);
+END;
diff --git a/test/data/Bertini_examples/Chap11AdvancedPosDim/LineCircle.print b/test/data/Bertini_examples/Chap11AdvancedPosDim/LineCircle.print
new file mode 100644
index 0000000..80822ae
--- /dev/null
+++ b/test/data/Bertini_examples/Chap11AdvancedPosDim/LineCircle.print
@@ -0,0 +1,11 @@
+% LineCircle.print
+CONFIG
+ TrackType:4; % print witness set
+ MPType:0; % print using double precision
+END;
+INPUT
+ function f;
+ variable_group x,y;
+
+ f = (x - y)*(x^2 + y^2 - 1);
+END;
diff --git a/test/data/Bertini_examples/Chap11AdvancedPosDim/MaxCodimension.input b/test/data/Bertini_examples/Chap11AdvancedPosDim/MaxCodimension.input
new file mode 100644
index 0000000..9ba9059
--- /dev/null
+++ b/test/data/Bertini_examples/Chap11AdvancedPosDim/MaxCodimension.input
@@ -0,0 +1,13 @@
+% MaxCodimension.input
+CONFIG
+ TrackType:1; % compute a numerical irred. decomp.
+ MaxCodimension:2; % for components of codim <= 2
+END;
+INPUT
+ variable_group x,y,z;
+ function f1,f2,f3;
+
+ f1 = x*(x^2-y-z^2);
+ f2 = x*(x+y+z^2-2)*(y-5);
+ f3 = x*(x^2+x-2)*(z-2);
+END;
diff --git a/test/data/Bertini_examples/Chap11AdvancedPosDim/SpecificCodimension.input b/test/data/Bertini_examples/Chap11AdvancedPosDim/SpecificCodimension.input
new file mode 100644
index 0000000..c3f1f28
--- /dev/null
+++ b/test/data/Bertini_examples/Chap11AdvancedPosDim/SpecificCodimension.input
@@ -0,0 +1,15 @@
+% SpecificCodimension.input
+% for components of codim = 2
+CONFIG
+ TrackType:1; % compute a numerical irred. decomp.
+ SpecificCodimension:2; % for components of codim = 2
+ WitnessGenType:1; % using dimension-by-dimension
+END;
+INPUT
+ variable_group x,y,z;
+ function f1,f2,f3;
+
+ f1 = x*(x^2-y-z^2);
+ f2 = x*(x+y+z^2-2)*(y-5);
+ f3 = x*(x^2+x-2)*(z-2);
+END;
diff --git a/test/data/Bertini_examples/Chap12Intersection/._.DS_Store b/test/data/Bertini_examples/Chap12Intersection/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap12Intersection/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap12Intersection/DiagonalIntersection.input b/test/data/Bertini_examples/Chap12Intersection/DiagonalIntersection.input
new file mode 100644
index 0000000..c3b31b3
--- /dev/null
+++ b/test/data/Bertini_examples/Chap12Intersection/DiagonalIntersection.input
@@ -0,0 +1,17 @@
+% DiagonalIntersection.input
+CONFIG
+ UserHomotopy:2;
+END;
+INPUT
+ function FA,FB,L1,L2;
+ variable_group x1,x2,y1,y2;
+ pathvariable T;
+ parameter t;
+ random gamma;
+
+ t = T;
+ FA = x1;
+ FB = y1*y2;
+ L1 = gamma*t*(2*x1 + x2 - 2) + (1-t)*(x1 - y1);
+ L2 = gamma*t*(x1 + 3*y2 + 4) + (1-t)*(x2 - y2);
+END;
diff --git a/test/data/Bertini_examples/Chap12Intersection/DiagonalIntersection.start b/test/data/Bertini_examples/Chap12Intersection/DiagonalIntersection.start
new file mode 100644
index 0000000..be88eae
--- /dev/null
+++ b/test/data/Bertini_examples/Chap12Intersection/DiagonalIntersection.start
@@ -0,0 +1,6 @@
+1
+
+0 0
+2 0
+-4 0
+0 0
diff --git a/test/data/Bertini_examples/Chap12Intersection/IntersectComponents.input b/test/data/Bertini_examples/Chap12Intersection/IntersectComponents.input
new file mode 100644
index 0000000..bc11465
--- /dev/null
+++ b/test/data/Bertini_examples/Chap12Intersection/IntersectComponents.input
@@ -0,0 +1,19 @@
+% IntersectComponents.input
+CONFIG
+ UserHomotopy:2;
+END;
+INPUT
+ function FA,FB,L1,L2,L3,L4;
+ variable_group x1,x2,x3,y1,y2,y3;
+ pathvariable T;
+ parameter t;
+ random gamma;
+
+ t = T;
+ FA = (x1*x2 - x3)*(x1^2 - x2);
+ FB = (y1*y2 - y3)*(y1^2 - y2);
+ L1 = gamma*t*(x1+2*x3-2) + (1-t)*(x1-y1);
+ L2 = gamma*t*(x2+x3-1) + (1-t)*(x2-y2);
+ L3 = gamma*t*(y1+2*y3-2) + (1-t)*(x3-y3);
+ L4 = gamma*t*(y2+y3-1) + (1-t)*(x1-2*x2+5*x3-3*y1-4*y2+y3-3);
+END;
diff --git a/test/data/Bertini_examples/Chap14RealSets/._.DS_Store b/test/data/Bertini_examples/Chap14RealSets/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap14RealSets/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap14RealSets/FritzJohnHomotopy.input b/test/data/Bertini_examples/Chap14RealSets/FritzJohnHomotopy.input
new file mode 100644
index 0000000..cb275c4
--- /dev/null
+++ b/test/data/Bertini_examples/Chap14RealSets/FritzJohnHomotopy.input
@@ -0,0 +1,24 @@
+% FritzJohnHomotopy.input
+CONFIG
+ UserHomotopy:2;
+END;
+INPUT
+ function F,G1,G2,patch;
+ variable_group x1,x2;
+ variable_group l0,l1;
+ constant y1,y2,eps,a0,a1;
+ pathvariable T;
+ parameter t;
+
+ t = T;
+ y1 = 0.5;
+ y2 = 0.8;
+ eps = 1.1 + 0.7*I;
+ a0 = -1.3;
+ a1 = 1.7;
+
+ F = x2^2 + x1^2*(x1-1)^3*(x1-2) - t*eps;
+ G1 = l0*(x1-y1) + l1*x1*(x1-1)^2*(6*x1^2-13*x1+4);
+ G2 = l0*(x2-y2) + 2*l1*x2;
+ patch = a0*l0 + a1*l1 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap14RealSets/FritzJohnInitial.input b/test/data/Bertini_examples/Chap14RealSets/FritzJohnInitial.input
new file mode 100644
index 0000000..ba821d2
--- /dev/null
+++ b/test/data/Bertini_examples/Chap14RealSets/FritzJohnInitial.input
@@ -0,0 +1,17 @@
+% FritzJohnInitial.input
+ function F,G1,G2,patch;
+ variable_group x1,x2;
+ variable_group l0,l1;
+ constant y1,y2,eps,a0,a1;
+
+ y1 = 0.5;
+ y2 = 0.8;
+ eps = 1.1 + 0.7*I;
+ a0 = -1.3;
+ a1 = 1.7;
+
+ F = x2^2 + x1^2*(x1-1)^3*(x1-2) - eps;
+ G1 = l0*(x1-y1) + l1*x1*(x1-1)^2*(6*x1^2-13*x1+4);
+ G2 = l0*(x2-y2) + 2*l1*x2;
+ patch = a0*l0 + a1*l1 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap16ProjectionsOfSets/._.DS_Store b/test/data/Bertini_examples/Chap16ProjectionsOfSets/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap16ProjectionsOfSets/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap16ProjectionsOfSets/Discriminant.input b/test/data/Bertini_examples/Chap16ProjectionsOfSets/Discriminant.input
new file mode 100644
index 0000000..873fb93
--- /dev/null
+++ b/test/data/Bertini_examples/Chap16ProjectionsOfSets/Discriminant.input
@@ -0,0 +1,23 @@
+% Discriminant.input
+CONFIG
+ UserHomotopy:2;
+END;
+INPUT
+ function f1,f2,l1,l2;
+ variable_group a,b,c;
+ hom_variable_group x,z;
+ constant a1,b1,c1;
+ random gamma;
+ pathvariable T;
+ parameter t;
+
+ t = T;
+ a1 = 1;
+ b1 = 2;
+ c1 = 1;
+
+ f1 = a*x^2 + b*x*z + c*z^2;
+ f2 = 2*a*x + b*z;
+ l1 = (a - 3*c - 4)*(1 - t + gamma*t) - (a1 - 3*c1 - 4)*(1 - t);
+ l2 = (b + 3*c + 2)*(1 - t + gamma*t) - (b1 + 3*c1 + 2)*(1 - t);
+END;
diff --git a/test/data/Bertini_examples/Chap16ProjectionsOfSets/Enneper.input b/test/data/Bertini_examples/Chap16ProjectionsOfSets/Enneper.input
new file mode 100644
index 0000000..dfd9568
--- /dev/null
+++ b/test/data/Bertini_examples/Chap16ProjectionsOfSets/Enneper.input
@@ -0,0 +1,12 @@
+% Enneper.input
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ function f1,f2,f3;
+ variable_group x,y,z,u,v;
+
+ f1 = 3*x - u*(1 - u^2/3 + v^2);
+ f2 = 3*y + v*(1 - v^2/3 + u^2);
+ f3 = 3*z - (u^2 - v^2);
+END;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/._.DS_Store b/test/data/Bertini_examples/Chap1PolynomialSystems/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap1PolynomialSystems/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/._CircleAndYaxisC0.input b/test/data/Bertini_examples/Chap1PolynomialSystems/._CircleAndYaxisC0.input
new file mode 100644
index 0000000..549cf11
Binary files /dev/null and b/test/data/Bertini_examples/Chap1PolynomialSystems/._CircleAndYaxisC0.input differ
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/CircleAndYaxisC0.input b/test/data/Bertini_examples/Chap1PolynomialSystems/CircleAndYaxisC0.input
new file mode 100644
index 0000000..61b5416
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/CircleAndYaxisC0.input
@@ -0,0 +1,10 @@
+ % CircleAndYaxisC0.input
+ function f,g;
+ variable_group x,y;
+ constant c;
+
+ c = 0;
+ f = (x-c)^2+y^2-1;
+ g = x;
+
+END;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/CircleAndYaxisC1.input b/test/data/Bertini_examples/Chap1PolynomialSystems/CircleAndYaxisC1.input
new file mode 100644
index 0000000..b19c224
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/CircleAndYaxisC1.input
@@ -0,0 +1,10 @@
+ % CircleAndYaxisC0.input
+ function f,g;
+ variable_group x,y;
+ constant c;
+
+ c = 1;
+ f = (x-c)^2+y^2-1;
+ g = x;
+
+END;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/degree10.input b/test/data/Bertini_examples/Chap1PolynomialSystems/degree10.input
new file mode 100644
index 0000000..56fc1c7
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/degree10.input
@@ -0,0 +1,9 @@
+% degree10.input
+CONFIG
+ FinalTol:1e-15;
+END;
+INPUT
+ variable_group z;
+ function p;
+ p = z^10 - 30*z^9 + 2;
+END;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/degree10eval.input b/test/data/Bertini_examples/Chap1PolynomialSystems/degree10eval.input
new file mode 100644
index 0000000..e394990
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/degree10eval.input
@@ -0,0 +1,11 @@
+% degree10eval.input
+CONFIG
+ TrackType:-4;
+ MPType:1;
+ Precision:128;
+END;
+INPUT
+ variable_group z;
+ function p;
+ p = z^10 - 30*z^9 + 2;
+END;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/degree10eval.points b/test/data/Bertini_examples/Chap1PolynomialSystems/degree10eval.points
new file mode 100644
index 0000000..7898259
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/degree10eval.points
@@ -0,0 +1,22 @@
+6
+
+30 0
+
+30.00000000000021 -1.2e-12
+
+7.422190004295883e-01 0.000000000000000e+00
+
+2.999999999999990e+01 1.776356839400250e-15
+
+0.742219000429588411304753220667e0 -0.107600627472146010258159776305e-26
+
+0.299999999999998983894731417796e2 -0.208679331633159200994841978461e-22
+
+% File: degree10eval.points
+% some points for evaluating the degree10.input problem
+% Try
+% >> bertini degree10eval.input degree10eval.points
+% z=30 is for illustration.
+% z=30.00000000000021 + -1.2e-12*I is a solution approximated using FinalTol:1e-11;
+% The next two are solutions approximated using FinalTol:1e-15;
+% The last two are solutions approximated using FinalTol:1e-19;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/input b/test/data/Bertini_examples/Chap1PolynomialSystems/input
new file mode 100644
index 0000000..b79526d
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/input
@@ -0,0 +1,7 @@
+ %input: our first input file
+ variable_group x,y;
+ function f,g;
+
+ f = x^2 - 1;
+ g = y^2 - 4;
+ END;
diff --git a/test/data/Bertini_examples/Chap1PolynomialSystems/subfunctions.input b/test/data/Bertini_examples/Chap1PolynomialSystems/subfunctions.input
new file mode 100644
index 0000000..cc93225
--- /dev/null
+++ b/test/data/Bertini_examples/Chap1PolynomialSystems/subfunctions.input
@@ -0,0 +1,9 @@
+% subfunctions.input
+INPUT
+ variable_group z;
+ function p;
+
+ a = z^3 + z + 1;
+ b = z^2 + 2;
+ p = a^4 - 5*b^3 + 6;
+END;
diff --git a/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircle.input b/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircle.input
new file mode 100644
index 0000000..1625c6b
--- /dev/null
+++ b/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircle.input
@@ -0,0 +1,16 @@
+%AroundTheUnitCircle.input
+CONFIG
+ UserHomotopy:1;
+END;
+
+INPUT
+ variable z;
+ function H;
+ parameter q1,q2;
+ pathvariable t;
+
+ q1 = cos(2*Pi*(1-t));
+ q2 = sin(2*Pi*(1-t));
+ s = q1 + I*q2;
+ H = z^2 - s;
+END;
diff --git a/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircle.start b/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircle.start
new file mode 100644
index 0000000..322e153
--- /dev/null
+++ b/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircle.start
@@ -0,0 +1,4 @@
+1
+
+1 0;
+%AroundTheUnitCircle.start
diff --git a/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircleAlt.input b/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircleAlt.input
new file mode 100644
index 0000000..0cf0866
--- /dev/null
+++ b/test/data/Bertini_examples/Chap2BasicContinuation/AroundTheUnitCircleAlt.input
@@ -0,0 +1,14 @@
+%AroundTheUnitCircleAlt.input
+CONFIG
+ UserHomotopy:1;
+END;
+
+INPUT
+ variable z;
+ function H;
+ parameter s;
+ pathvariable t;
+
+ s = exp(2*Pi*I*(1-t));
+ H = z^2 - s;
+END;
diff --git a/test/data/Bertini_examples/Chap4ProjectiveSpace/._.DS_Store b/test/data/Bertini_examples/Chap4ProjectiveSpace/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap4ProjectiveSpace/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap4ProjectiveSpace/Eigenvalue2x2.input b/test/data/Bertini_examples/Chap4ProjectiveSpace/Eigenvalue2x2.input
new file mode 100644
index 0000000..273795f
--- /dev/null
+++ b/test/data/Bertini_examples/Chap4ProjectiveSpace/Eigenvalue2x2.input
@@ -0,0 +1,11 @@
+% Eigenvalue2x2.input
+% A simple eigenvalue/eigenvector problem
+% illustrating usage of hom_variable_group.
+INPUT
+ function f1,f2;
+ variable_group lambda;
+ hom_variable_group v1,v2;
+
+ f1 = (1-lambda)*v1 + 2*v2;
+ f2 = 3*v1 + (4-lambda)*v2;
+END;
diff --git a/test/data/Bertini_examples/Chap4ProjectiveSpace/GeneralizedEigenvalue.input b/test/data/Bertini_examples/Chap4ProjectiveSpace/GeneralizedEigenvalue.input
new file mode 100644
index 0000000..b83279f
--- /dev/null
+++ b/test/data/Bertini_examples/Chap4ProjectiveSpace/GeneralizedEigenvalue.input
@@ -0,0 +1,11 @@
+% GeneralizedEigenvalue.input
+% Simple example of using two homogeneous groups.
+% This is a 2x2 generalized eigenvalue problem.
+INPUT
+ function f1,f2;
+ hom_variable_group v1,v2;
+ hom_variable_group mu,lambda;
+
+ f1 = mu*(1*v1 + 2*v2) - lambda*( 4*v1 - 2*v2);
+ f2 = mu*(2*v1 + 4*v2) - lambda*(-2*v1 + 1*v2);
+END;
diff --git a/test/data/Bertini_examples/Chap4ProjectiveSpace/TwoCircles.input b/test/data/Bertini_examples/Chap4ProjectiveSpace/TwoCircles.input
new file mode 100644
index 0000000..ac0c74d
--- /dev/null
+++ b/test/data/Bertini_examples/Chap4ProjectiveSpace/TwoCircles.input
@@ -0,0 +1,13 @@
+% TwoCircles.input
+% Intersection of two circles
+CONFIG
+ % Force accurate determination of diverging paths
+ SecurityLevel:1;
+END;
+INPUT
+ function circle1, circle2;
+ variable_group x, y;
+
+ circle1 = x^2 + y^2 - 1;
+ circle2 = (x-1)^2 + (y+1)^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/._.DS_Store b/test/data/Bertini_examples/Chap5HomotopyTypes/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap5HomotopyTypes/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/LagrangePoints.input b/test/data/Bertini_examples/Chap5HomotopyTypes/LagrangePoints.input
new file mode 100644
index 0000000..c168f35
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/LagrangePoints.input
@@ -0,0 +1,33 @@
+% LagrangePoints.input
+% Equilibria for a 3rd small body rotating with two large
+% ones in circular orbit
+INPUT
+ function fma1,fma2,dist13,dist23,fma3x,fma3y;
+ % definition: w = omega^2 d12^3/(G m2)
+ % The remaining variables are nondimensionalized as
+ % ratio to d12.
+ variable_group w;
+ variable_group r1;
+ variable_group x,y,d13,d23;
+ constant mu;
+
+ % choose value for the mass ratio
+ mu = 9;
+
+ % the following eliminates r2
+ r2 = 1-r1;
+ % f=ma on mass 1
+ fma1 = w*r1 - 1;
+ % f=ma on mass 2
+ fma2 = w*r2 - mu;
+
+ % distance m1 to m3
+ dist13 = (x-r1)^2 + y^2 - d13^2;
+ % distance m2 to m3
+ dist23 = (x+r2)^2 + y^2 - d23^2;
+
+ % f=ma on m3
+ a = w*d13^3*d23^3; b1 = mu*d23^3; b2 = d13^3;
+ fma3x = a*x + b1*(r1-x) + b2*(-r2-x);
+ fma3y = a*y + b1*(-y) + b2*(-y);
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/LagrangePoints_regen.input b/test/data/Bertini_examples/Chap5HomotopyTypes/LagrangePoints_regen.input
new file mode 100644
index 0000000..a17b7a9
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/LagrangePoints_regen.input
@@ -0,0 +1,37 @@
+% LagrangePoints_regen.input
+% Equilibria for a 3rd small body rotating with two large
+% ones in circular orbit
+% Use regeneration instead of a basic 3-homogeneous homotopy
+CONFIG
+ UseRegeneration:1;
+END;
+INPUT
+ function fma1,fma2,dist13,dist23,fma3x,fma3y;
+ % definition: w = omega^2 d12^3/(G m2)
+ % The remaining variables are nondimensionalized as
+ % ratio to d12.
+ variable_group w;
+ variable_group r1;
+ variable_group x,y,d13,d23;
+ constant mu;
+
+ % choose value for the mass ratio
+ mu = 9;
+
+ % the following eliminates r2
+ r2 = 1-r1;
+ % f=ma on mass 1
+ fma1 = w*r1 - 1;
+ % f=ma on mass 2
+ fma2 = w*r2 - mu;
+
+ % distance m1 to m3
+ dist13 = (x-r1)^2 + y^2 - d13^2;
+ % distance m2 to m3
+ dist23 = (x+r2)^2 + y^2 - d23^2;
+
+ % f=ma on m3
+ a = w*d13^3*d23^3; b1 = mu*d23^3; b2 = d13^3;
+ fma3x = a*x + b1*(r1-x) + b2*(-r2-x);
+ fma3y = a*y + b1*(-y) + b2*(-y);
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/SixR_2hom.input b/test/data/Bertini_examples/Chap5HomotopyTypes/SixR_2hom.input
new file mode 100644
index 0000000..265cc49
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/SixR_2hom.input
@@ -0,0 +1,67 @@
+% SixR_2hom.input
+% Random six-revolute serial link robot
+% Variables in 2 groups
+INPUT
+ % link lengths
+ random a1,a2,a3,a4,a5;
+ % link offsets
+ random d2,d3,d4,d5;
+ % twist cosines
+ random c1,c2,c3,c4,c5;
+ % endpoint position
+ random px,py,pz;
+ % joint 6 orientation
+ random z6x,z6y,z6z;
+ % joint 1 orientation (fixed)
+ constant z1x,z1y,z1z;
+ z1x=0; z1y=0; z1z=1;
+
+ variable_group z2x,z2y,z2z, z4x,z4y,z4z;
+ variable_group z3x,z3y,z3z, z5x,z5y,z5z;
+
+ function unit2, unit3, unit4, unit5;
+ function twist1, twist2, twist3, twist4, twist5;
+ function X,Y,Z;
+
+ unit2 = z2x^2 + z2y^2 + z2z^2 -1;
+ unit3 = z3x^2 + z3y^2 + z3z^2 -1;
+ unit4 = z4x^2 + z4y^2 + z4z^2 -1;
+ unit5 = z5x^2 + z5y^2 + z5z^2 -1;
+ twist1 = z1x*z2x + z1y*z2y + z1z*z2z - c1;
+ twist2 = z2x*z3x + z2y*z3y + z2z*z3z - c2;
+ twist3 = z3x*z4x + z3y*z4y + z3z*z4z - c3;
+ twist4 = z4x*z5x + z4y*z5y + z4z*z5z - c4;
+ twist5 = z5x*z6x + z5y*z6y + z5z*z6z - c5;
+ % form cross products
+ x1x = z1y*z2z - z1z*z2y;
+ x2x = z2y*z3z - z2z*z3y;
+ x3x = z3y*z4z - z3z*z4y;
+ x4x = z4y*z5z - z4z*z5y;
+ x5x = z5y*z6z - z5z*z6y;
+ x1y = z1z*z2x - z1x*z2z;
+ x2y = z2z*z3x - z2x*z3z;
+ x3y = z3z*z4x - z3x*z4z;
+ x4y = z4z*z5x - z4x*z5z;
+ x5y = z5z*z6x - z5x*z6z;
+ x1z = z1x*z2y - z1y*z2x;
+ x2z = z2x*z3y - z2y*z3x;
+ x3z = z3x*z4y - z3y*z4x;
+ x4z = z4x*z5y - z4y*z5x;
+ x5z = z5x*z6y - z5y*z6x;
+ % position
+ X = a1*x1x + d2*z2x +
+ a2*x2x + d3*z3x +
+ a3*x3x + d4*z4x +
+ a4*x4x + d5*z5x +
+ a5*x5x - px;
+ Y = a1*x1y + d2*z2y +
+ a2*x2y + d3*z3y +
+ a3*x3y + d4*z4y +
+ a4*x4y + d5*z5y +
+ a5*x5y - py;
+ Z = a1*x1z + d2*z2z +
+ a2*x2z + d3*z3z +
+ a3*x3z + d4*z4z +
+ a4*x4z + d5*z5z +
+ a5*x5z - pz;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/SixR_4hom.input b/test/data/Bertini_examples/Chap5HomotopyTypes/SixR_4hom.input
new file mode 100644
index 0000000..5358115
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/SixR_4hom.input
@@ -0,0 +1,69 @@
+% SixR_4hom.input
+% Random six-revolute serial link robot
+% Variables in 4 groups
+INPUT
+ % link lengths
+ random a1,a2,a3,a4,a5;
+ % link offsets
+ random d2,d3,d4,d5;
+ % twist cosines
+ random c1,c2,c3,c4,c5;
+ % endpoint position
+ random px,py,pz;
+ % joint 6 orientation
+ random z6x,z6y,z6z;
+ % joint 1 orientation (fixed)
+ constant z1x,z1y,z1z;
+ z1x=0; z1y=0; z1z=1;
+
+ variable_group z2x,z2y,z2z;
+ variable_group z3x,z3y,z3z;
+ variable_group z4x,z4y,z4z;
+ variable_group z5x,z5y,z5z;
+
+ function unit2, unit3, unit4, unit5;
+ function twist1, twist2, twist3, twist4, twist5;
+ function X,Y,Z;
+
+ unit2 = z2x^2 + z2y^2 + z2z^2 -1;
+ unit3 = z3x^2 + z3y^2 + z3z^2 -1;
+ unit4 = z4x^2 + z4y^2 + z4z^2 -1;
+ unit5 = z5x^2 + z5y^2 + z5z^2 -1;
+ twist1 = z1x*z2x + z1y*z2y + z1z*z2z - c1;
+ twist2 = z2x*z3x + z2y*z3y + z2z*z3z - c2;
+ twist3 = z3x*z4x + z3y*z4y + z3z*z4z - c3;
+ twist4 = z4x*z5x + z4y*z5y + z4z*z5z - c4;
+ twist5 = z5x*z6x + z5y*z6y + z5z*z6z - c5;
+ % form cross products
+ x1x = z1y*z2z - z1z*z2y;
+ x2x = z2y*z3z - z2z*z3y;
+ x3x = z3y*z4z - z3z*z4y;
+ x4x = z4y*z5z - z4z*z5y;
+ x5x = z5y*z6z - z5z*z6y;
+ x1y = z1z*z2x - z1x*z2z;
+ x2y = z2z*z3x - z2x*z3z;
+ x3y = z3z*z4x - z3x*z4z;
+ x4y = z4z*z5x - z4x*z5z;
+ x5y = z5z*z6x - z5x*z6z;
+ x1z = z1x*z2y - z1y*z2x;
+ x2z = z2x*z3y - z2y*z3x;
+ x3z = z3x*z4y - z3y*z4x;
+ x4z = z4x*z5y - z4y*z5x;
+ x5z = z5x*z6y - z5y*z6x;
+ % position
+ X = a1*x1x + d2*z2x +
+ a2*x2x + d3*z3x +
+ a3*x3x + d4*z4x +
+ a4*x4x + d5*z5x +
+ a5*x5x - px;
+ Y = a1*x1y + d2*z2y +
+ a2*x2y + d3*z3y +
+ a3*x3y + d4*z4y +
+ a4*x4y + d5*z5y +
+ a5*x5y - py;
+ Z = a1*x1z + d2*z2z +
+ a2*x2z + d3*z3z +
+ a3*x3z + d4*z4z +
+ a4*x4z + d5*z5z +
+ a5*x5z - pz;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/TwoHyperbolas_1Hom.input b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoHyperbolas_1Hom.input
new file mode 100644
index 0000000..1028d57
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoHyperbolas_1Hom.input
@@ -0,0 +1,7 @@
+% TwoHyperbolas_1Hom.input
+variable_group x,y;
+function f1,f2;
+
+f1=x*y-1;
+f2=x*y+x-y-1 ;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/TwoHyperbolas_2Hom.input b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoHyperbolas_2Hom.input
new file mode 100644
index 0000000..155ae05
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoHyperbolas_2Hom.input
@@ -0,0 +1,8 @@
+% TwoHyperbolas_2Hom.input
+variable_group x;
+variable_group y;
+function f1,f2;
+
+f1=x*y-1;
+f2=x*y+x-y-1 ;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/TwoQuadrics_1hom.input b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoQuadrics_1hom.input
new file mode 100644
index 0000000..2f006c3
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoQuadrics_1hom.input
@@ -0,0 +1,7 @@
+% TwoQuadrics_1hom.input
+INPUT
+ function f1, f2;
+ variable_group x,y;
+ f1 = x*y - 1;
+ f2 = x^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/TwoQuadrics_2hom.input b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoQuadrics_2hom.input
new file mode 100644
index 0000000..17e0b8d
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoQuadrics_2hom.input
@@ -0,0 +1,8 @@
+% TwoQuadrics_2hom.input
+INPUT
+ function f1, f2;
+ variable_group x;
+ variable_group y;
+ f1 = x*y - 1;
+ f2 = x^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/TwoSpheres_OneCone.input b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoSpheres_OneCone.input
new file mode 100644
index 0000000..b84d10c
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/TwoSpheres_OneCone.input
@@ -0,0 +1,13 @@
+% TwoSpheres_OneCone.input
+CONFIG
+ UseRegeneration:1;
+END;
+INPUT
+ function sphere1, sphere2, cone;
+ variable_group x,y,z;
+ random cx1,cy1,cz1,r1, cx2,cy2,cz2,r2, cx3,cy3,r3;
+
+ sphere1 = (x-cx1)^2 + (y-cy1)^2 + (z-cz1)^2 - r1^2;
+ sphere2 = (x-cx2)^2 + (y-cy2)^2 + (z-cz2)^2 - r2^2;
+ cone = (x-z*cx3)^2 + (y-z*cy3)^2 - (z*r3)^2;
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen1group.input b/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen1group.input
new file mode 100644
index 0000000..8723bb4
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen1group.input
@@ -0,0 +1,149 @@
+% Nine-point path synthesis problem for four-bar linkages.
+% All variables in one group
+CONFIG
+ UseRegeneration:1;
+ TrackTolBeforeEG:1e-8;
+ TrackTolDuringEG:1e-8;
+ SliceTolBeforeEG:1e-8;
+ SliceTolDuringEG:1e-8;
+ SecurityMaxNorm:1e7;
+ EndpointFiniteThreshold:1e7;
+ PathTruncationThreshold:1e7;
+ SampleFactor:0.1;
+END;
+
+INPUT
+ function f1,f2,f3,f4,f5,f6,f7,f8;
+ % Vectors a1,b1, a2,b2 in isotropic coordinates
+ variable_group a1,A1, b1,B1, a2,A2, b2,B2;
+ % (pk,PK), k=1,...,8, are the precision points in isotropic coords
+ random p1,P1, p2,P2, p3,P3, p4,P4, p5,P5, p6,P6, p7,P7, p8,P8;
+
+ % These highest terms do not depend on the precision points:
+ n1 = A1*b1;
+ N1 = a1*B1;
+ n2 = A2*b2;
+ N2 = a2*B2;
+ % nN = |n N| = det[n1 N1; n2 N2]
+ nN = n1*N2 - n2*N1;
+
+ % For each precision point we have an equation:
+ % f = |v u|*|v U| + |u U|^2,
+ % where
+ % v = [v1+n1+N1; v2+n2+N2],
+ % u = [w1-n1; w2-n2], U = [W1-N1; W2-N2];
+ % Expand the expressions far enough so that the cancellation
+ % of the highest terms can be exposed.
+ % Repeat this template for k=1,...,8
+ % v1k = pk*Pk - a1*Pk - A1*pk;
+ % v2k = pk*Pk - a2*Pk - A2*pk;
+ % w1k = b1*Pk; W1k = B1*pk;
+ % w2k = b2*Pk; W2k = B2*pk;
+ % These sums are the entries in v
+ % s1k = v1k + n1 + N1;
+ % s2k = v2k + n2 + N2;
+ % These are the lower-order terms (that do not cancel)
+ % vuLowk = s1k*w2k - s2k*w1k - v1k*n2 + v2k*n1;
+ % vULowk = s1k*W2k - s2k*W1k - v1k*N2 + v2k*N1;
+ % uULowk = w1k*W2k - w2k*W1k - w1k*N2 + w2k*N1 - n1*W2k + n2*W1k;
+ % Finally, form f, with degree 8 terms cancelled out.
+ % (highest terms are |n N|*|N n| + |n N|^2 = 0)
+ % fk = vuLowk*vULowk - vuLowk*nN + vULowk*nN + uULowk^2 + 2*uULowk*nN;
+
+ % k=1
+ v11 = p1*P1 - a1*P1 - A1*p1;
+ v21 = p1*P1 - a2*P1 - A2*p1;
+ w11 = b1*P1; W11 = B1*p1;
+ w21 = b2*P1; W21 = B2*p1;
+ s11 = v11 + n1 + N1;
+ s21 = v21 + n2 + N2;
+ vuLow1 = s11*w21 - s21*w11 - v11*n2 + v21*n1;
+ vULow1 = s11*W21 - s21*W11 - v11*N2 + v21*N1;
+ uULow1 = w11*W21 - w21*W11 - w11*N2 + w21*N1 - n1*W21 + n2*W11;
+ f1 = vuLow1*vULow1 - vuLow1*nN + vULow1*nN + uULow1^2 + 2*uULow1*nN;
+
+ % k=2
+ v12 = p2*P2 - a1*P2 - A1*p2;
+ v22 = p2*P2 - a2*P2 - A2*p2;
+ w12 = b1*P2; W12 = B1*p2;
+ w22 = b2*P2; W22 = B2*p2;
+ s12 = v12 + n1 + N1;
+ s22 = v22 + n2 + N2;
+ vuLow2 = s12*w22 - s22*w12 - v12*n2 + v22*n1;
+ vULow2 = s12*W22 - s22*W12 - v12*N2 + v22*N1;
+ uULow2 = w12*W22 - w22*W12 - w12*N2 + w22*N1 - n1*W22 + n2*W12;
+ f2 = vuLow2*vULow2 - vuLow2*nN + vULow2*nN + uULow2^2 + 2*uULow2*nN;
+
+ % k=3
+ v13 = p3*P3 - a1*P3 - A1*p3;
+ v23 = p3*P3 - a2*P3 - A2*p3;
+ w13 = b1*P3; W13 = B1*p3;
+ w23 = b2*P3; W23 = B2*p3;
+ s13 = v13 + n1 + N1;
+ s23 = v23 + n2 + N2;
+ vuLow3 = s13*w23 - s23*w13 - v13*n2 + v23*n1;
+ vULow3 = s13*W23 - s23*W13 - v13*N2 + v23*N1;
+ uULow3 = w13*W23 - w23*W13 - w13*N2 + w23*N1 - n1*W23 + n2*W13;
+ f3 = vuLow3*vULow3 - vuLow3*nN + vULow3*nN + uULow3^2 + 2*uULow3*nN;
+
+ % k=4
+ v14 = p4*P4 - a1*P4 - A1*p4;
+ v24 = p4*P4 - a2*P4 - A2*p4;
+ w14 = b1*P4; W14 = B1*p4;
+ w24 = b2*P4; W24 = B2*p4;
+ s14 = v14 + n1 + N1;
+ s24 = v24 + n2 + N2;
+ vuLow4 = s14*w24 - s24*w14 - v14*n2 + v24*n1;
+ vULow4 = s14*W24 - s24*W14 - v14*N2 + v24*N1;
+ uULow4 = w14*W24 - w24*W14 - w14*N2 + w24*N1 - n1*W24 + n2*W14;
+ f4 = vuLow4*vULow4 - vuLow4*nN + vULow4*nN + uULow4^2 + 2*uULow4*nN;
+
+ % k=5
+ v15 = p5*P5 - a1*P5 - A1*p5;
+ v25 = p5*P5 - a2*P5 - A2*p5;
+ w15 = b1*P5; W15 = B1*p5;
+ w25 = b2*P5; W25 = B2*p5;
+ s15 = v15 + n1 + N1;
+ s25 = v25 + n2 + N2;
+ vuLow5 = s15*w25 - s25*w15 - v15*n2 + v25*n1;
+ vULow5 = s15*W25 - s25*W15 - v15*N2 + v25*N1;
+ uULow5 = w15*W25 - w25*W15 - w15*N2 + w25*N1 - n1*W25 + n2*W15;
+ f5 = vuLow5*vULow5 - vuLow5*nN + vULow5*nN + uULow5^2 + 2*uULow5*nN;
+
+ % k=6
+ v16 = p6*P6 - a1*P6 - A1*p6;
+ v26 = p6*P6 - a2*P6 - A2*p6;
+ w16 = b1*P6; W16 = B1*p6;
+ w26 = b2*P6; W26 = B2*p6;
+ s16 = v16 + n1 + N1;
+ s26 = v26 + n2 + N2;
+ vuLow6 = s16*w26 - s26*w16 - v16*n2 + v26*n1;
+ vULow6 = s16*W26 - s26*W16 - v16*N2 + v26*N1;
+ uULow6 = w16*W26 - w26*W16 - w16*N2 + w26*N1 - n1*W26 + n2*W16;
+ f6 = vuLow6*vULow6 - vuLow6*nN + vULow6*nN + uULow6^2 + 2*uULow6*nN;
+
+ % k=7
+ v17 = p7*P7 - a1*P7 - A1*p7;
+ v27 = p7*P7 - a2*P7 - A2*p7;
+ w17 = b1*P7; W17 = B1*p7;
+ w27 = b2*P7; W27 = B2*p7;
+ s17 = v17 + n1 + N1;
+ s27 = v27 + n2 + N2;
+ vuLow7 = s17*w27 - s27*w17 - v17*n2 + v27*n1;
+ vULow7 = s17*W27 - s27*W17 - v17*N2 + v27*N1;
+ uULow7 = w17*W27 - w27*W17 - w17*N2 + w27*N1 - n1*W27 + n2*W17;
+ f7 = vuLow7*vULow7 - vuLow7*nN + vULow7*nN + uULow7^2 + 2*uULow7*nN;
+
+ % k=8
+ v18 = p8*P8 - a1*P8 - A1*p8;
+ v28 = p8*P8 - a2*P8 - A2*p8;
+ w18 = b1*P8; W18 = B1*p8;
+ w28 = b2*P8; W28 = B2*p8;
+ s18 = v18 + n1 + N1;
+ s28 = v28 + n2 + N2;
+ vuLow8 = s18*w28 - s28*w18 - v18*n2 + v28*n1;
+ vULow8 = s18*W28 - s28*W18 - v18*N2 + v28*N1;
+ uULow8 = w18*W28 - w28*W18 - w18*N2 + w28*N1 - n1*W28 + n2*W18;
+ f8 = vuLow8*vULow8 - vuLow8*nN + vULow8*nN + uULow8^2 + 2*uULow8*nN;
+
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen2groups.input b/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen2groups.input
new file mode 100644
index 0000000..d3fb80a
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen2groups.input
@@ -0,0 +1,150 @@
+% Nine-point path synthesis problem for four-bar linkages.
+% Variables in 2 groups
+CONFIG
+ UseRegeneration:1;
+ TrackTolBeforeEG:1e-8;
+ TrackTolDuringEG:1e-8;
+ SliceTolBeforeEG:1e-8;
+ SliceTolDuringEG:1e-8;
+ SecurityMaxNorm:1e7;
+ EndpointFiniteThreshold:1e7;
+ PathTruncationThreshold:1e7;
+ SampleFactor:0.1;
+END;
+
+INPUT
+ function f1,f2,f3,f4,f5,f6,f7,f8;
+ % Vectors a1,b1, a2,b2 in isotropic coordinates
+ variable_group a1,A1, b1,B1;
+ variable_group a2,A2, b2,B2;
+ % (pk,PK), k=1,...,8, are the precision points in isotropic coords
+ random p1,P1, p2,P2, p3,P3, p4,P4, p5,P5, p6,P6, p7,P7, p8,P8;
+
+ % These highest terms do not depend on the precision points:
+ n1 = A1*b1;
+ N1 = a1*B1;
+ n2 = A2*b2;
+ N2 = a2*B2;
+ % nN = |n N| = det[n1 N1; n2 N2]
+ nN = n1*N2 - n2*N1;
+
+ % For each precision point we have an equation:
+ % f = |v u|*|v U| + |u U|^2,
+ % where
+ % v = [v1+n1+N1; v2+n2+N2],
+ % u = [w1-n1; w2-n2], U = [W1-N1; W2-N2];
+ % Expand the expressions far enough so that the cancellation
+ % of the highest terms can be exposed.
+ % Repeat this template for k=1,...,8
+ % v1k = pk*Pk - a1*Pk - A1*pk;
+ % v2k = pk*Pk - a2*Pk - A2*pk;
+ % w1k = b1*Pk; W1k = B1*pk;
+ % w2k = b2*Pk; W2k = B2*pk;
+ % These sums are the entries in v
+ % s1k = v1k + n1 + N1;
+ % s2k = v2k + n2 + N2;
+ % These are the lower-order terms (that do not cancel)
+ % vuLowk = s1k*w2k - s2k*w1k - v1k*n2 + v2k*n1;
+ % vULowk = s1k*W2k - s2k*W1k - v1k*N2 + v2k*N1;
+ % uULowk = w1k*W2k - w2k*W1k - w1k*N2 + w2k*N1 - n1*W2k + n2*W1k;
+ % Finally, form f, with degree 8 terms cancelled out.
+ % (highest terms are |n N|*|N n| + |n N|^2 = 0)
+ % fk = vuLowk*vULowk - vuLowk*nN + vULowk*nN + uULowk^2 + 2*uULowk*nN;
+
+ % k=1
+ v11 = p1*P1 - a1*P1 - A1*p1;
+ v21 = p1*P1 - a2*P1 - A2*p1;
+ w11 = b1*P1; W11 = B1*p1;
+ w21 = b2*P1; W21 = B2*p1;
+ s11 = v11 + n1 + N1;
+ s21 = v21 + n2 + N2;
+ vuLow1 = s11*w21 - s21*w11 - v11*n2 + v21*n1;
+ vULow1 = s11*W21 - s21*W11 - v11*N2 + v21*N1;
+ uULow1 = w11*W21 - w21*W11 - w11*N2 + w21*N1 - n1*W21 + n2*W11;
+ f1 = vuLow1*vULow1 - vuLow1*nN + vULow1*nN + uULow1^2 + 2*uULow1*nN;
+
+ % k=2
+ v12 = p2*P2 - a1*P2 - A1*p2;
+ v22 = p2*P2 - a2*P2 - A2*p2;
+ w12 = b1*P2; W12 = B1*p2;
+ w22 = b2*P2; W22 = B2*p2;
+ s12 = v12 + n1 + N1;
+ s22 = v22 + n2 + N2;
+ vuLow2 = s12*w22 - s22*w12 - v12*n2 + v22*n1;
+ vULow2 = s12*W22 - s22*W12 - v12*N2 + v22*N1;
+ uULow2 = w12*W22 - w22*W12 - w12*N2 + w22*N1 - n1*W22 + n2*W12;
+ f2 = vuLow2*vULow2 - vuLow2*nN + vULow2*nN + uULow2^2 + 2*uULow2*nN;
+
+ % k=3
+ v13 = p3*P3 - a1*P3 - A1*p3;
+ v23 = p3*P3 - a2*P3 - A2*p3;
+ w13 = b1*P3; W13 = B1*p3;
+ w23 = b2*P3; W23 = B2*p3;
+ s13 = v13 + n1 + N1;
+ s23 = v23 + n2 + N2;
+ vuLow3 = s13*w23 - s23*w13 - v13*n2 + v23*n1;
+ vULow3 = s13*W23 - s23*W13 - v13*N2 + v23*N1;
+ uULow3 = w13*W23 - w23*W13 - w13*N2 + w23*N1 - n1*W23 + n2*W13;
+ f3 = vuLow3*vULow3 - vuLow3*nN + vULow3*nN + uULow3^2 + 2*uULow3*nN;
+
+ % k=4
+ v14 = p4*P4 - a1*P4 - A1*p4;
+ v24 = p4*P4 - a2*P4 - A2*p4;
+ w14 = b1*P4; W14 = B1*p4;
+ w24 = b2*P4; W24 = B2*p4;
+ s14 = v14 + n1 + N1;
+ s24 = v24 + n2 + N2;
+ vuLow4 = s14*w24 - s24*w14 - v14*n2 + v24*n1;
+ vULow4 = s14*W24 - s24*W14 - v14*N2 + v24*N1;
+ uULow4 = w14*W24 - w24*W14 - w14*N2 + w24*N1 - n1*W24 + n2*W14;
+ f4 = vuLow4*vULow4 - vuLow4*nN + vULow4*nN + uULow4^2 + 2*uULow4*nN;
+
+ % k=5
+ v15 = p5*P5 - a1*P5 - A1*p5;
+ v25 = p5*P5 - a2*P5 - A2*p5;
+ w15 = b1*P5; W15 = B1*p5;
+ w25 = b2*P5; W25 = B2*p5;
+ s15 = v15 + n1 + N1;
+ s25 = v25 + n2 + N2;
+ vuLow5 = s15*w25 - s25*w15 - v15*n2 + v25*n1;
+ vULow5 = s15*W25 - s25*W15 - v15*N2 + v25*N1;
+ uULow5 = w15*W25 - w25*W15 - w15*N2 + w25*N1 - n1*W25 + n2*W15;
+ f5 = vuLow5*vULow5 - vuLow5*nN + vULow5*nN + uULow5^2 + 2*uULow5*nN;
+
+ % k=6
+ v16 = p6*P6 - a1*P6 - A1*p6;
+ v26 = p6*P6 - a2*P6 - A2*p6;
+ w16 = b1*P6; W16 = B1*p6;
+ w26 = b2*P6; W26 = B2*p6;
+ s16 = v16 + n1 + N1;
+ s26 = v26 + n2 + N2;
+ vuLow6 = s16*w26 - s26*w16 - v16*n2 + v26*n1;
+ vULow6 = s16*W26 - s26*W16 - v16*N2 + v26*N1;
+ uULow6 = w16*W26 - w26*W16 - w16*N2 + w26*N1 - n1*W26 + n2*W16;
+ f6 = vuLow6*vULow6 - vuLow6*nN + vULow6*nN + uULow6^2 + 2*uULow6*nN;
+
+ % k=7
+ v17 = p7*P7 - a1*P7 - A1*p7;
+ v27 = p7*P7 - a2*P7 - A2*p7;
+ w17 = b1*P7; W17 = B1*p7;
+ w27 = b2*P7; W27 = B2*p7;
+ s17 = v17 + n1 + N1;
+ s27 = v27 + n2 + N2;
+ vuLow7 = s17*w27 - s27*w17 - v17*n2 + v27*n1;
+ vULow7 = s17*W27 - s27*W17 - v17*N2 + v27*N1;
+ uULow7 = w17*W27 - w27*W17 - w17*N2 + w27*N1 - n1*W27 + n2*W17;
+ f7 = vuLow7*vULow7 - vuLow7*nN + vULow7*nN + uULow7^2 + 2*uULow7*nN;
+
+ % k=8
+ v18 = p8*P8 - a1*P8 - A1*p8;
+ v28 = p8*P8 - a2*P8 - A2*p8;
+ w18 = b1*P8; W18 = B1*p8;
+ w28 = b2*P8; W28 = B2*p8;
+ s18 = v18 + n1 + N1;
+ s28 = v28 + n2 + N2;
+ vuLow8 = s18*w28 - s28*w18 - v18*n2 + v28*n1;
+ vULow8 = s18*W28 - s28*W18 - v18*N2 + v28*N1;
+ uULow8 = w18*W28 - w28*W18 - w18*N2 + w28*N1 - n1*W28 + n2*W18;
+ f8 = vuLow8*vULow8 - vuLow8*nN + vULow8*nN + uULow8^2 + 2*uULow8*nN;
+
+END;
diff --git a/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen4groups.input b/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen4groups.input
new file mode 100644
index 0000000..2308a72
--- /dev/null
+++ b/test/data/Bertini_examples/Chap5HomotopyTypes/ninepoint_regen4groups.input
@@ -0,0 +1,152 @@
+% Nine-point path synthesis problem for four-bar linkages.
+% Variables in 4 groups
+CONFIG
+ UseRegeneration:1;
+ TrackTolBeforeEG:1e-8;
+ TrackTolDuringEG:1e-8;
+ SliceTolBeforeEG:1e-8;
+ SliceTolDuringEG:1e-8;
+ SecurityMaxNorm:1e7;
+ EndpointFiniteThreshold:1e7;
+ PathTruncationThreshold:1e7;
+ SampleFactor:0.1;
+END;
+
+INPUT
+ function f1,f2,f3,f4,f5,f6,f7,f8;
+ % Vectors a1,b1, a2,b2 in isotropic coordinates
+ variable_group a1,b1;
+ variable_group a2,b2;
+ variable_group A1,B1;
+ variable_group A2,B2;
+ % (pk,PK), k=1,...,8, are the precision points in isotropic coords
+ random p1,P1, p2,P2, p3,P3, p4,P4, p5,P5, p6,P6, p7,P7, p8,P8;
+
+ % These highest terms do not depend on the precision points:
+ n1 = A1*b1;
+ N1 = a1*B1;
+ n2 = A2*b2;
+ N2 = a2*B2;
+ % nN = |n N| = det[n1 N1; n2 N2]
+ nN = n1*N2 - n2*N1;
+
+ % For each precision point we have an equation:
+ % f = |v u|*|v U| + |u U|^2,
+ % where
+ % v = [v1+n1+N1; v2+n2+N2],
+ % u = [w1-n1; w2-n2], U = [W1-N1; W2-N2];
+ % Expand the expressions far enough so that the cancellation
+ % of the highest terms can be exposed.
+ % Repeat this template for k=1,...,8
+ % v1k = pk*Pk - a1*Pk - A1*pk;
+ % v2k = pk*Pk - a2*Pk - A2*pk;
+ % w1k = b1*Pk; W1k = B1*pk;
+ % w2k = b2*Pk; W2k = B2*pk;
+ % These sums are the entries in v
+ % s1k = v1k + n1 + N1;
+ % s2k = v2k + n2 + N2;
+ % These are the lower-order terms (that do not cancel)
+ % vuLowk = s1k*w2k - s2k*w1k - v1k*n2 + v2k*n1;
+ % vULowk = s1k*W2k - s2k*W1k - v1k*N2 + v2k*N1;
+ % uULowk = w1k*W2k - w2k*W1k - w1k*N2 + w2k*N1 - n1*W2k + n2*W1k;
+ % Finally, form f, with degree 8 terms cancelled out.
+ % (highest terms are |n N|*|N n| + |n N|^2 = 0)
+ % fk = vuLowk*vULowk - vuLowk*nN + vULowk*nN + uULowk^2 + 2*uULowk*nN;
+
+ % k=1
+ v11 = p1*P1 - a1*P1 - A1*p1;
+ v21 = p1*P1 - a2*P1 - A2*p1;
+ w11 = b1*P1; W11 = B1*p1;
+ w21 = b2*P1; W21 = B2*p1;
+ s11 = v11 + n1 + N1;
+ s21 = v21 + n2 + N2;
+ vuLow1 = s11*w21 - s21*w11 - v11*n2 + v21*n1;
+ vULow1 = s11*W21 - s21*W11 - v11*N2 + v21*N1;
+ uULow1 = w11*W21 - w21*W11 - w11*N2 + w21*N1 - n1*W21 + n2*W11;
+ f1 = vuLow1*vULow1 - vuLow1*nN + vULow1*nN + uULow1^2 + 2*uULow1*nN;
+
+ % k=2
+ v12 = p2*P2 - a1*P2 - A1*p2;
+ v22 = p2*P2 - a2*P2 - A2*p2;
+ w12 = b1*P2; W12 = B1*p2;
+ w22 = b2*P2; W22 = B2*p2;
+ s12 = v12 + n1 + N1;
+ s22 = v22 + n2 + N2;
+ vuLow2 = s12*w22 - s22*w12 - v12*n2 + v22*n1;
+ vULow2 = s12*W22 - s22*W12 - v12*N2 + v22*N1;
+ uULow2 = w12*W22 - w22*W12 - w12*N2 + w22*N1 - n1*W22 + n2*W12;
+ f2 = vuLow2*vULow2 - vuLow2*nN + vULow2*nN + uULow2^2 + 2*uULow2*nN;
+
+ % k=3
+ v13 = p3*P3 - a1*P3 - A1*p3;
+ v23 = p3*P3 - a2*P3 - A2*p3;
+ w13 = b1*P3; W13 = B1*p3;
+ w23 = b2*P3; W23 = B2*p3;
+ s13 = v13 + n1 + N1;
+ s23 = v23 + n2 + N2;
+ vuLow3 = s13*w23 - s23*w13 - v13*n2 + v23*n1;
+ vULow3 = s13*W23 - s23*W13 - v13*N2 + v23*N1;
+ uULow3 = w13*W23 - w23*W13 - w13*N2 + w23*N1 - n1*W23 + n2*W13;
+ f3 = vuLow3*vULow3 - vuLow3*nN + vULow3*nN + uULow3^2 + 2*uULow3*nN;
+
+ % k=4
+ v14 = p4*P4 - a1*P4 - A1*p4;
+ v24 = p4*P4 - a2*P4 - A2*p4;
+ w14 = b1*P4; W14 = B1*p4;
+ w24 = b2*P4; W24 = B2*p4;
+ s14 = v14 + n1 + N1;
+ s24 = v24 + n2 + N2;
+ vuLow4 = s14*w24 - s24*w14 - v14*n2 + v24*n1;
+ vULow4 = s14*W24 - s24*W14 - v14*N2 + v24*N1;
+ uULow4 = w14*W24 - w24*W14 - w14*N2 + w24*N1 - n1*W24 + n2*W14;
+ f4 = vuLow4*vULow4 - vuLow4*nN + vULow4*nN + uULow4^2 + 2*uULow4*nN;
+
+ % k=5
+ v15 = p5*P5 - a1*P5 - A1*p5;
+ v25 = p5*P5 - a2*P5 - A2*p5;
+ w15 = b1*P5; W15 = B1*p5;
+ w25 = b2*P5; W25 = B2*p5;
+ s15 = v15 + n1 + N1;
+ s25 = v25 + n2 + N2;
+ vuLow5 = s15*w25 - s25*w15 - v15*n2 + v25*n1;
+ vULow5 = s15*W25 - s25*W15 - v15*N2 + v25*N1;
+ uULow5 = w15*W25 - w25*W15 - w15*N2 + w25*N1 - n1*W25 + n2*W15;
+ f5 = vuLow5*vULow5 - vuLow5*nN + vULow5*nN + uULow5^2 + 2*uULow5*nN;
+
+ % k=6
+ v16 = p6*P6 - a1*P6 - A1*p6;
+ v26 = p6*P6 - a2*P6 - A2*p6;
+ w16 = b1*P6; W16 = B1*p6;
+ w26 = b2*P6; W26 = B2*p6;
+ s16 = v16 + n1 + N1;
+ s26 = v26 + n2 + N2;
+ vuLow6 = s16*w26 - s26*w16 - v16*n2 + v26*n1;
+ vULow6 = s16*W26 - s26*W16 - v16*N2 + v26*N1;
+ uULow6 = w16*W26 - w26*W16 - w16*N2 + w26*N1 - n1*W26 + n2*W16;
+ f6 = vuLow6*vULow6 - vuLow6*nN + vULow6*nN + uULow6^2 + 2*uULow6*nN;
+
+ % k=7
+ v17 = p7*P7 - a1*P7 - A1*p7;
+ v27 = p7*P7 - a2*P7 - A2*p7;
+ w17 = b1*P7; W17 = B1*p7;
+ w27 = b2*P7; W27 = B2*p7;
+ s17 = v17 + n1 + N1;
+ s27 = v27 + n2 + N2;
+ vuLow7 = s17*w27 - s27*w17 - v17*n2 + v27*n1;
+ vULow7 = s17*W27 - s27*W17 - v17*N2 + v27*N1;
+ uULow7 = w17*W27 - w27*W17 - w17*N2 + w27*N1 - n1*W27 + n2*W17;
+ f7 = vuLow7*vULow7 - vuLow7*nN + vULow7*nN + uULow7^2 + 2*uULow7*nN;
+
+ % k=8
+ v18 = p8*P8 - a1*P8 - A1*p8;
+ v28 = p8*P8 - a2*P8 - A2*p8;
+ w18 = b1*P8; W18 = B1*p8;
+ w28 = b2*P8; W28 = B2*p8;
+ s18 = v18 + n1 + N1;
+ s28 = v28 + n2 + N2;
+ vuLow8 = s18*w28 - s28*w18 - v18*n2 + v28*n1;
+ vULow8 = s18*W28 - s28*W18 - v18*N2 + v28*N1;
+ uULow8 = w18*W28 - w28*W18 - w18*N2 + w28*N1 - n1*W28 + n2*W18;
+ f8 = vuLow8*vULow8 - vuLow8*nN + vULow8*nN + uULow8^2 + 2*uULow8*nN;
+
+END;
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/._.DS_Store b/test/data/Bertini_examples/Chap6ParameterHomotopy/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap6ParameterHomotopy/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/LagrangePoints.input b/test/data/Bertini_examples/Chap6ParameterHomotopy/LagrangePoints.input
new file mode 100644
index 0000000..c168f35
--- /dev/null
+++ b/test/data/Bertini_examples/Chap6ParameterHomotopy/LagrangePoints.input
@@ -0,0 +1,33 @@
+% LagrangePoints.input
+% Equilibria for a 3rd small body rotating with two large
+% ones in circular orbit
+INPUT
+ function fma1,fma2,dist13,dist23,fma3x,fma3y;
+ % definition: w = omega^2 d12^3/(G m2)
+ % The remaining variables are nondimensionalized as
+ % ratio to d12.
+ variable_group w;
+ variable_group r1;
+ variable_group x,y,d13,d23;
+ constant mu;
+
+ % choose value for the mass ratio
+ mu = 9;
+
+ % the following eliminates r2
+ r2 = 1-r1;
+ % f=ma on mass 1
+ fma1 = w*r1 - 1;
+ % f=ma on mass 2
+ fma2 = w*r2 - mu;
+
+ % distance m1 to m3
+ dist13 = (x-r1)^2 + y^2 - d13^2;
+ % distance m2 to m3
+ dist23 = (x+r2)^2 + y^2 - d23^2;
+
+ % f=ma on m3
+ a = w*d13^3*d23^3; b1 = mu*d23^3; b2 = d13^3;
+ fma3x = a*x + b1*(r1-x) + b2*(-r2-x);
+ fma3y = a*y + b1*(-y) + b2*(-y);
+END;
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/LagrangePoints_parameter.input b/test/data/Bertini_examples/Chap6ParameterHomotopy/LagrangePoints_parameter.input
new file mode 100644
index 0000000..74e7a35
--- /dev/null
+++ b/test/data/Bertini_examples/Chap6ParameterHomotopy/LagrangePoints_parameter.input
@@ -0,0 +1,35 @@
+% Lagrange Points problem
+% Equilibria for a 3rd small body rotating with two large
+% ones in circular orbit
+%
+% Set up for parameter homotopy
+CONFIG
+ ParameterHomotopy:1; % change to 2 after ab initio run is done
+END;
+INPUT
+ function fma1,fma2,dist13,dist23,fma3x,fma3y;
+ % definition: w = omega^2 d12^3/(G m2)
+ % The remaining variables are nondimensionalized as
+ % ratio to d12.
+ variable_group w;
+ variable_group r1;
+ variable_group x,y,d13,d23;
+ parameter mu;
+
+ % the following eliminates r2
+ r2 = 1-r1;
+ % f=ma on mass 1
+ fma1 = w*r1 - 1;
+ % f=ma on mass 2
+ fma2 = w*r2 - mu;
+
+ % distance m1 to m3
+ dist13 = (x-r1)^2 + y^2 - d13^2;
+ % distance m2 to m3
+ dist23 = (x+r2)^2 + y^2 - d23^2;
+
+ % f=ma on m3
+ a = w*d13^3*d23^3; b1 = mu*d23^3; b2 = d13^3;
+ fma3x = a*x + b1*(r1-x) + b2*(-r2-x);
+ fma3y = a*y + b1*(-y) + b2*(-y);
+END;
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/SixR_parameter.input b/test/data/Bertini_examples/Chap6ParameterHomotopy/SixR_parameter.input
new file mode 100644
index 0000000..6a618fb
--- /dev/null
+++ b/test/data/Bertini_examples/Chap6ParameterHomotopy/SixR_parameter.input
@@ -0,0 +1,72 @@
+% SixR_parameter.input
+%
+% Input file for solving 6R inverse kinematics by parameter homotopy
+%
+CONFIG
+ % Set to 1 for ab initio run, change to 2 for parameter runs.
+ ParameterHomotopy:1;
+END
+INPUT
+ % link lengths
+ parameter a1,a2,a3,a4,a5;
+ % link offsets
+ parameter d2,d3,d4,d5;
+ % twist cosines
+ parameter c1,c2,c3,c4,c5;
+ % endpoint position
+ parameter px,py,pz;
+ % joint 6 orientation
+ parameter z6x,z6y,z6z;
+ % joint 1 orientation (fixed)
+ constant z1x,z1y,z1z;
+ z1x=0; z1y=0; z1z=1;
+
+ variable_group z2x,z2y,z2z, z4x,z4y,z4z;
+ variable_group z3x,z3y,z3z, z5x,z5y,z5z;
+
+ function unit2, unit3, unit4, unit5;
+ function twist1, twist2, twist3, twist4, twist5;
+ function X,Y,Z;
+
+ unit2 = z2x^2 + z2y^2 + z2z^2 -1;
+ unit3 = z3x^2 + z3y^2 + z3z^2 -1;
+ unit4 = z4x^2 + z4y^2 + z4z^2 -1;
+ unit5 = z5x^2 + z5y^2 + z5z^2 -1;
+ twist1 = z1x*z2x + z1y*z2y + z1z*z2z - c1;
+ twist2 = z2x*z3x + z2y*z3y + z2z*z3z - c2;
+ twist3 = z3x*z4x + z3y*z4y + z3z*z4z - c3;
+ twist4 = z4x*z5x + z4y*z5y + z4z*z5z - c4;
+ twist5 = z5x*z6x + z5y*z6y + z5z*z6z - c5;
+ % form cross products
+ x1x = z1y*z2z - z1z*z2y;
+ x2x = z2y*z3z - z2z*z3y;
+ x3x = z3y*z4z - z3z*z4y;
+ x4x = z4y*z5z - z4z*z5y;
+ x5x = z5y*z6z - z5z*z6y;
+ x1y = z1z*z2x - z1x*z2z;
+ x2y = z2z*z3x - z2x*z3z;
+ x3y = z3z*z4x - z3x*z4z;
+ x4y = z4z*z5x - z4x*z5z;
+ x5y = z5z*z6x - z5x*z6z;
+ x1z = z1x*z2y - z1y*z2x;
+ x2z = z2x*z3y - z2y*z3x;
+ x3z = z3x*z4y - z3y*z4x;
+ x4z = z4x*z5y - z4y*z5x;
+ x5z = z5x*z6y - z5y*z6x;
+ % position
+ X = a1*x1x + d2*z2x +
+ a2*x2x + d3*z3x +
+ a3*x3x + d4*z4x +
+ a4*x4x + d5*z5x +
+ a5*x5x - px;
+ Y = a1*x1y + d2*z2y +
+ a2*x2y + d3*z3y +
+ a3*x3y + d4*z4y +
+ a4*x4y + d5*z5y +
+ a5*x5y - py;
+ Z = a1*x1z + d2*z2z +
+ a2*x2z + d3*z3z +
+ a3*x3z + d4*z4z +
+ a4*x4z + d5*z5z +
+ a5*x5z - pz;
+END;
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/StewartGough.input b/test/data/Bertini_examples/Chap6ParameterHomotopy/StewartGough.input
new file mode 100644
index 0000000..957e1fc
--- /dev/null
+++ b/test/data/Bertini_examples/Chap6ParameterHomotopy/StewartGough.input
@@ -0,0 +1,125 @@
+% Stewart-Gough platform forward kinematics
+%
+% This is the general case.
+CONFIG
+ % Set to 1 for ab initio run, change to 2 for parameter runs.
+ ParameterHomotopy:1;
+END
+
+
+INPUT
+ % The two rigid bodies have 6 point pairs at known distances.
+ % 6 points on the stationary rigid body
+ parameter a1x,a1y,a1z, a2x,a2y,a2z, a3x,a3y,a3z, a4x,a4y,a4z, a5x,a5y,a5z, a6x,a6y,a6z;
+ % 6 points on the moving rigid body
+ parameter b1x,b1y,b1z, b2x,b2y,b2z, b3x,b3y,b3z, b4x,b4y,b4z, b5x,b5y,b5z, b6x,b6y,b6z;
+ % squared distances between point pairs
+ parameter d1,d2,d3,d4,d5,d6;
+
+ % These will be the squared distance functions
+ function f1,f2,f3,f4,f5,f6;
+ % The Study quadric
+ function Study;
+
+ % Use Study coordinates for the position & orientation of the moving body.
+ hom_variable_group e0,e1,e2,e3,g0,g1,g2,g3;
+
+ % Let X be the 4x4 representation of quaternion (x0,x1,x2,x3)
+ % So
+ % X = [ x0 -x1 -x2 -x3
+ % x1 x0 -x3 x2
+ % x2 x3 x0 -x1
+ % x3 -x2 x1 x0 ]
+ % Treat vector (v1,v2,v3) as quaternion (0,v1,v2,v3).
+ % We also say that Re(x) = x0 or equivalently, Re(X) = x0*I.
+
+ % Quaternions obey the relation X*X' = |(x0,x1,x2,x3)|^2 = |X|^2
+ % Let ee = E*E', gg = G*G':
+ ee = e0^2 + e1^2 + e2^2 +e3^2;
+ gg = g0^2 + g1^2 + g2^2 +g3^2;
+
+ % After transformation, a point b = (b1,b2,b3) becomes
+ % Transf(b) = (E*B*E' + G*E')/ee
+ % with the Study quadric side condition of
+ % Study = Re(G*E') = 0
+ Study = g0*e0 + g1*e1 + g2*e2 + g3*e3;
+
+ % Accordingly, the governing equations are the squared distance relations
+ % (*) d = | (E*B*E' + G*E')/ee - A |^2
+ % = [ (E*B*E' + G*E')/ee - A ]*[ (E*B'*E' + E*G')/ee - A']
+ % After expanding this, several instances of E*E' = ee*I appear. After
+ % simplifying ee/ee = 1 (cases of ee=0 are meaningless) and then
+ % clearing the denominator by multiplying by ee, (*) becomes
+ % a quadric relation in E,G, with A,B,d considered constants.
+ % We apply this 6 times for d_i, a_i, b_i.
+
+ % We simplify (*) with some vector algebra, where the following
+ % terms appear:
+ R11 = e0^2+e1^2-e2^2-e3^2;
+ R12 = 2*(-e0*e3+e1*e2);
+ R13 = 2*( e0*e2+e1*e3);
+ R21 = 2*( e0*e3+e2*e1);
+ R22 = e0^2-e1^2+e2^2-e3^2;
+ R23 = 2*(-e0*e1+e2*e3);
+ R31 = 2*(-e0*e2+e3*e1);
+ R32 = 2*( e0*e1+e3*e2);
+ R33 = e0^2-e1^2-e2^2+e3^2;
+ u1 = g0*e1 - e0*g1;
+ u2 = g0*e2 - e0*g2;
+ u3 = g0*e3 - e0*g3;
+ v1 = g2*e3 - g3*e2;
+ v2 = g3*e1 - g1*e3;
+ v3 = g1*e2 - g2*e1;
+
+ % Now, we form the 6 distance equations.
+ % Write it in terms of J, then substitute J = 1,...,6
+% fJ = (aJx^2+aJy^2+aJz^2+bJx^2+bJy^2+bJz^2-dJ)*ee + gg +
+% 2*(u1*(aJx-bJx) + u2*(aJy-bJy) + u3*(aJz-bJz)) +
+% 2*(v1*(aJx+bJx) + v2*(aJy+bJy) + v3*(aJz+bJz)) +
+% -2*( aJx*(R11*bJx+R12*bJy+R13*bJz) +
+% aJy*(R21*bJx+R22*bJy+R23*bJz) +
+% aJz*(R31*bJx+R32*bJy+R33*bJz) ) ;
+
+ f1 = (a1x^2+a1y^2+a1z^2+b1x^2+b1y^2+b1z^2-d1)*ee + gg +
+ 2*(u1*(a1x-b1x) + u2*(a1y-b1y) + u3*(a1z-b1z)) +
+ 2*(v1*(a1x+b1x) + v2*(a1y+b1y) + v3*(a1z+b1z)) +
+ -2*( a1x*(R11*b1x+R12*b1y+R13*b1z) +
+ a1y*(R21*b1x+R22*b1y+R23*b1z) +
+ a1z*(R31*b1x+R32*b1y+R33*b1z) ) ;
+
+ f2 = (a2x^2+a2y^2+a2z^2+b2x^2+b2y^2+b2z^2-d2)*ee + gg +
+ 2*(u1*(a2x-b2x) + u2*(a2y-b2y) + u3*(a2z-b2z)) +
+ 2*(v1*(a2x+b2x) + v2*(a2y+b2y) + v3*(a2z+b2z)) +
+ -2*( a2x*(R11*b2x+R12*b2y+R13*b2z) +
+ a2y*(R21*b2x+R22*b2y+R23*b2z) +
+ a2z*(R31*b2x+R32*b2y+R33*b2z) ) ;
+
+ f3 = (a3x^2+a3y^2+a3z^2+b3x^2+b3y^2+b3z^2-d3)*ee + gg +
+ 2*(u1*(a3x-b3x) + u2*(a3y-b3y) + u3*(a3z-b3z)) +
+ 2*(v1*(a3x+b3x) + v2*(a3y+b3y) + v3*(a3z+b3z)) +
+ -2*( a3x*(R11*b3x+R12*b3y+R13*b3z) +
+ a3y*(R21*b3x+R22*b3y+R23*b3z) +
+ a3z*(R31*b3x+R32*b3y+R33*b3z) ) ;
+
+ f4 = (a4x^2+a4y^2+a4z^2+b4x^2+b4y^2+b4z^2-d4)*ee + gg +
+ 2*(u1*(a4x-b4x) + u2*(a4y-b4y) + u3*(a4z-b4z)) +
+ 2*(v1*(a4x+b4x) + v2*(a4y+b4y) + v3*(a4z+b4z)) +
+ -2*( a4x*(R11*b4x+R12*b4y+R13*b4z) +
+ a4y*(R21*b4x+R22*b4y+R23*b4z) +
+ a4z*(R31*b4x+R32*b4y+R33*b4z) ) ;
+
+ f5 = (a5x^2+a5y^2+a5z^2+b5x^2+b5y^2+b5z^2-d5)*ee + gg +
+ 2*(u1*(a5x-b5x) + u2*(a5y-b5y) + u3*(a5z-b5z)) +
+ 2*(v1*(a5x+b5x) + v2*(a5y+b5y) + v3*(a5z+b5z)) +
+ -2*( a5x*(R11*b5x+R12*b5y+R13*b5z) +
+ a5y*(R21*b5x+R22*b5y+R23*b5z) +
+ a5z*(R31*b5x+R32*b5y+R33*b5z) ) ;
+
+ f6 = (a6x^2+a6y^2+a6z^2+b6x^2+b6y^2+b6z^2-d6)*ee + gg +
+ 2*(u1*(a6x-b6x) + u2*(a6y-b6y) + u3*(a6z-b6z)) +
+ 2*(v1*(a6x+b6x) + v2*(a6y+b6y) + v3*(a6z+b6z)) +
+ -2*( a6x*(R11*b6x+R12*b6y+R13*b6z) +
+ a6y*(R21*b6x+R22*b6y+R23*b6z) +
+ a6z*(R31*b6x+R32*b6y+R33*b6z) ) ;
+
+END
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/ninepoint_parameter.input b/test/data/Bertini_examples/Chap6ParameterHomotopy/ninepoint_parameter.input
new file mode 100644
index 0000000..bd80d70
--- /dev/null
+++ b/test/data/Bertini_examples/Chap6ParameterHomotopy/ninepoint_parameter.input
@@ -0,0 +1,161 @@
+% Nine-point path synthesis problem for four-bar linkages.
+%
+% Variables in 2 groups
+% For the ab initio run:
+% with UseRegeneration:0;, this will use 645,120 paths
+% with UseRegeneration:1;, the path count is reduced to 152,224 of
+% which only 48,704 are used in the last (most expensive) stage
+%
+% For subsequent parameter homotopy runs:
+% taking advantage of symmetries, all runs after the ab initio one
+% can be done with only 1442 paths.
+%
+CONFIG
+ ParameterHomotopy:1; % change to 2 after ab initio run is done
+ UseRegeneration:1;
+ TrackTolBeforeEG:1e-8;
+ TrackTolDuringEG:1e-8;
+ SliceTolBeforeEG:1e-8;
+ SliceTolDuringEG:1e-8;
+ SecurityMaxNorm:1e7;
+ EndpointFiniteThreshold:1e7;
+ PathTruncationThreshold:1e7;
+ SampleFactor:0.1;
+END;
+
+INPUT
+ function f1,f2,f3,f4,f5,f6,f7,f8;
+ % Vectors a1,b1, a2,b2 in isotropic coordinates
+ variable_group a1,A1, b1,B1;
+ variable_group a2,A2, b2,B2;
+ % (pk,PK), k=1,...,8, are the precision points in isotropic coords
+ parameter p1,P1, p2,P2, p3,P3, p4,P4, p5,P5, p6,P6, p7,P7, p8,P8;
+
+ % These highest terms do not depend on the precision points:
+ n1 = A1*b1;
+ N1 = a1*B1;
+ n2 = A2*b2;
+ N2 = a2*B2;
+ % nN = |n N| = det[n1 N1; n2 N2]
+ nN = n1*N2 - n2*N1;
+
+ % For each precision point we have an equation:
+ % f = |v u|*|v U| + |u U|^2,
+ % where
+ % v = [v1+n1+N1; v2+n2+N2],
+ % u = [w1-n1; w2-n2], U = [W1-N1; W2-N2];
+ % Expand the expressions far enough so that the cancellation
+ % of the highest terms can be exposed.
+ % Repeat this template for k=1,...,8
+ % v1k = pk*Pk - a1*Pk - A1*pk;
+ % v2k = pk*Pk - a2*Pk - A2*pk;
+ % w1k = b1*Pk; W1k = B1*pk;
+ % w2k = b2*Pk; W2k = B2*pk;
+ % These sums are the entries in v
+ % s1k = v1k + n1 + N1;
+ % s2k = v2k + n2 + N2;
+ % These are the lower-order terms (that do not cancel)
+ % vuLowk = s1k*w2k - s2k*w1k - v1k*n2 + v2k*n1;
+ % vULowk = s1k*W2k - s2k*W1k - v1k*N2 + v2k*N1;
+ % uULowk = w1k*W2k - w2k*W1k - w1k*N2 + w2k*N1 - n1*W2k + n2*W1k;
+ % Finally, form f, with degree 8 terms cancelled out.
+ % (highest terms are |n N|*|N n| + |n N|^2 = 0)
+ % fk = vuLowk*vULowk - vuLowk*nN + vULowk*nN + uULowk^2 + 2*uULowk*nN;
+
+ % k=1
+ v11 = p1*P1 - a1*P1 - A1*p1;
+ v21 = p1*P1 - a2*P1 - A2*p1;
+ w11 = b1*P1; W11 = B1*p1;
+ w21 = b2*P1; W21 = B2*p1;
+ s11 = v11 + n1 + N1;
+ s21 = v21 + n2 + N2;
+ vuLow1 = s11*w21 - s21*w11 - v11*n2 + v21*n1;
+ vULow1 = s11*W21 - s21*W11 - v11*N2 + v21*N1;
+ uULow1 = w11*W21 - w21*W11 - w11*N2 + w21*N1 - n1*W21 + n2*W11;
+ f1 = vuLow1*vULow1 - vuLow1*nN + vULow1*nN + uULow1^2 + 2*uULow1*nN;
+
+ % k=2
+ v12 = p2*P2 - a1*P2 - A1*p2;
+ v22 = p2*P2 - a2*P2 - A2*p2;
+ w12 = b1*P2; W12 = B1*p2;
+ w22 = b2*P2; W22 = B2*p2;
+ s12 = v12 + n1 + N1;
+ s22 = v22 + n2 + N2;
+ vuLow2 = s12*w22 - s22*w12 - v12*n2 + v22*n1;
+ vULow2 = s12*W22 - s22*W12 - v12*N2 + v22*N1;
+ uULow2 = w12*W22 - w22*W12 - w12*N2 + w22*N1 - n1*W22 + n2*W12;
+ f2 = vuLow2*vULow2 - vuLow2*nN + vULow2*nN + uULow2^2 + 2*uULow2*nN;
+
+ % k=3
+ v13 = p3*P3 - a1*P3 - A1*p3;
+ v23 = p3*P3 - a2*P3 - A2*p3;
+ w13 = b1*P3; W13 = B1*p3;
+ w23 = b2*P3; W23 = B2*p3;
+ s13 = v13 + n1 + N1;
+ s23 = v23 + n2 + N2;
+ vuLow3 = s13*w23 - s23*w13 - v13*n2 + v23*n1;
+ vULow3 = s13*W23 - s23*W13 - v13*N2 + v23*N1;
+ uULow3 = w13*W23 - w23*W13 - w13*N2 + w23*N1 - n1*W23 + n2*W13;
+ f3 = vuLow3*vULow3 - vuLow3*nN + vULow3*nN + uULow3^2 + 2*uULow3*nN;
+
+ % k=4
+ v14 = p4*P4 - a1*P4 - A1*p4;
+ v24 = p4*P4 - a2*P4 - A2*p4;
+ w14 = b1*P4; W14 = B1*p4;
+ w24 = b2*P4; W24 = B2*p4;
+ s14 = v14 + n1 + N1;
+ s24 = v24 + n2 + N2;
+ vuLow4 = s14*w24 - s24*w14 - v14*n2 + v24*n1;
+ vULow4 = s14*W24 - s24*W14 - v14*N2 + v24*N1;
+ uULow4 = w14*W24 - w24*W14 - w14*N2 + w24*N1 - n1*W24 + n2*W14;
+ f4 = vuLow4*vULow4 - vuLow4*nN + vULow4*nN + uULow4^2 + 2*uULow4*nN;
+
+ % k=5
+ v15 = p5*P5 - a1*P5 - A1*p5;
+ v25 = p5*P5 - a2*P5 - A2*p5;
+ w15 = b1*P5; W15 = B1*p5;
+ w25 = b2*P5; W25 = B2*p5;
+ s15 = v15 + n1 + N1;
+ s25 = v25 + n2 + N2;
+ vuLow5 = s15*w25 - s25*w15 - v15*n2 + v25*n1;
+ vULow5 = s15*W25 - s25*W15 - v15*N2 + v25*N1;
+ uULow5 = w15*W25 - w25*W15 - w15*N2 + w25*N1 - n1*W25 + n2*W15;
+ f5 = vuLow5*vULow5 - vuLow5*nN + vULow5*nN + uULow5^2 + 2*uULow5*nN;
+
+ % k=6
+ v16 = p6*P6 - a1*P6 - A1*p6;
+ v26 = p6*P6 - a2*P6 - A2*p6;
+ w16 = b1*P6; W16 = B1*p6;
+ w26 = b2*P6; W26 = B2*p6;
+ s16 = v16 + n1 + N1;
+ s26 = v26 + n2 + N2;
+ vuLow6 = s16*w26 - s26*w16 - v16*n2 + v26*n1;
+ vULow6 = s16*W26 - s26*W16 - v16*N2 + v26*N1;
+ uULow6 = w16*W26 - w26*W16 - w16*N2 + w26*N1 - n1*W26 + n2*W16;
+ f6 = vuLow6*vULow6 - vuLow6*nN + vULow6*nN + uULow6^2 + 2*uULow6*nN;
+
+ % k=7
+ v17 = p7*P7 - a1*P7 - A1*p7;
+ v27 = p7*P7 - a2*P7 - A2*p7;
+ w17 = b1*P7; W17 = B1*p7;
+ w27 = b2*P7; W27 = B2*p7;
+ s17 = v17 + n1 + N1;
+ s27 = v27 + n2 + N2;
+ vuLow7 = s17*w27 - s27*w17 - v17*n2 + v27*n1;
+ vULow7 = s17*W27 - s27*W17 - v17*N2 + v27*N1;
+ uULow7 = w17*W27 - w27*W17 - w17*N2 + w27*N1 - n1*W27 + n2*W17;
+ f7 = vuLow7*vULow7 - vuLow7*nN + vULow7*nN + uULow7^2 + 2*uULow7*nN;
+
+ % k=8
+ v18 = p8*P8 - a1*P8 - A1*p8;
+ v28 = p8*P8 - a2*P8 - A2*p8;
+ w18 = b1*P8; W18 = B1*p8;
+ w28 = b2*P8; W28 = B2*p8;
+ s18 = v18 + n1 + N1;
+ s28 = v28 + n2 + N2;
+ vuLow8 = s18*w28 - s28*w18 - v18*n2 + v28*n1;
+ vULow8 = s18*W28 - s28*W18 - v18*N2 + v28*N1;
+ uULow8 = w18*W28 - w28*W18 - w18*N2 + w28*N1 - n1*W28 + n2*W18;
+ f8 = vuLow8*vULow8 - vuLow8*nN + vULow8*nN + uULow8^2 + 2*uULow8*nN;
+
+END;
diff --git a/test/data/Bertini_examples/Chap6ParameterHomotopy/sextic.input b/test/data/Bertini_examples/Chap6ParameterHomotopy/sextic.input
new file mode 100644
index 0000000..6f5299d
--- /dev/null
+++ b/test/data/Bertini_examples/Chap6ParameterHomotopy/sextic.input
@@ -0,0 +1,10 @@
+% sextic.input
+CONFIG
+ ParameterHomotopy:1; % setting for ab initio run
+END;
+INPUT
+ function f;
+ variable_group x;
+ parameter a0,a1,a2,a3,a4,a5,a6;
+ f = a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))));
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/._.DS_Store b/test/data/Bertini_examples/Chap7AdvancedIsolated/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap7AdvancedIsolated/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/CircleParabola_eval.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/CircleParabola_eval.input
new file mode 100644
index 0000000..56060be
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/CircleParabola_eval.input
@@ -0,0 +1,14 @@
+% CircleParabola_eval.input
+CONFIG
+ TrackType:-3; % evaluate system and Jacobian
+ % use 64-bit precision
+ MPType:1;
+ Precision:64;
+END;
+INPUT
+ function circle,parabola;
+ variable_group x,y;
+
+ circle = x^2 + (y-1)^2 - 1;
+ parabola = y - 2*x^2;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/CircleParabola_newton.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/CircleParabola_newton.input
new file mode 100644
index 0000000..8d21618
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/CircleParabola_newton.input
@@ -0,0 +1,15 @@
+% CircleParabola_newton.input
+CONFIG
+ % Perform a Newton iteration & approximate the condition number
+ TrackType:-1;
+ % use 64-bit precision
+ MPType:1;
+ Precision:64;
+END;
+INPUT
+ function circle,parabola;
+ variable_group x,y;
+
+ circle = x^2 + (y-1)^2 - 1;
+ parabola = y - 2*x^2;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/CondNumCalc.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/CondNumCalc.input
new file mode 100644
index 0000000..88b43db
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/CondNumCalc.input
@@ -0,0 +1,17 @@
+% CondNumCalc.input
+CONFIG
+ % Perform a Newton iteration & approximate the condition number
+ TrackType:-1;
+ % Utilize 256-bit fixed precision
+ MPType:1;
+ Precision:256;
+ % fix a seed for the random number generator
+ RandomSeed:1934835;
+END;
+INPUT
+ function circle,parabola;
+ variable_group x,y;
+
+ circle = x^2 + (y-1)^2 - 1;
+ parabola = y - 2*x^2;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/CondNumCalc.start b/test/data/Bertini_examples/Chap7AdvancedIsolated/CondNumCalc.start
new file mode 100644
index 0000000..8500b86
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/CondNumCalc.start
@@ -0,0 +1,14 @@
+4
+
+-8.660254037844386e-01 9.492190020110591e-17
+1.500000000000000e+00 6.120321263680673e-17
+
+8.660254037844388e-01 -2.186564731360141e-16
+1.500000000000000e+00 -1.412715430748612e-16
+
+-2.213743081408535e-13 -1.498562286411079e-13
+2.540827022107365e-15 -1.330798662382149e-15
+
+2.878540067625655e-13 1.392857465195220e-13
+3.125787117584775e-15 -1.703491954589669e-15
+% CondNumCalc.start
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/FixedPoint.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/FixedPoint.input
new file mode 100644
index 0000000..67bd114
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/FixedPoint.input
@@ -0,0 +1,15 @@
+% FixedPoint.input
+CONFIG
+ % Use a fixed-point homotopy to sharpen
+ ParameterHomotopy:2;
+ FinalTol:1e-20;
+END;
+INPUT
+ function parabola,twolines
+ variable_group x,y;
+ parameter t,x0,y0;
+ random gamma;
+
+ parabola = (1-t)*(y - x^2) + gamma*t*(x - x0);
+ twolines = (1-t)*(x^2 - y^2) + gamma*t*(y - y0);
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/FunctionEval.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/FunctionEval.input
new file mode 100644
index 0000000..2c9be70
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/FunctionEval.input
@@ -0,0 +1,17 @@
+% FunctionEval.input
+CONFIG
+ % Evaluate a user-defined homotopy using 64-bit precision
+ UserHomotopy:1;
+ TrackType:-4;
+ MPType:1;
+ Precision:64;
+END;
+INPUT
+ function f;
+ variable x;
+ pathvariable T;
+ parameter t;
+ t = T;
+
+ f = exp(sin(x/(1+x))) + 1/cos(x-2) - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/FunctionEval.start b/test/data/Bertini_examples/Chap7AdvancedIsolated/FunctionEval.start
new file mode 100644
index 0000000..0144348
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/FunctionEval.start
@@ -0,0 +1,4 @@
+1
+
+-0.5 0
+% FunctionEval.start
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/HighCondNum.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/HighCondNum.input
new file mode 100644
index 0000000..ec4ffba
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/HighCondNum.input
@@ -0,0 +1,7 @@
+% HighCondNum.input
+ function f,g;
+ variable_group x,y;
+
+ f = y - x^10;
+ g = y - 1e-10;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/HighCondNum_sharpen.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/HighCondNum_sharpen.input
new file mode 100644
index 0000000..2f0b4d2
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/HighCondNum_sharpen.input
@@ -0,0 +1,12 @@
+% HighCondNum_sharpen.input
+CONFIG
+ SharpenOnly:1; % use the sharpening module
+ CondNumThreshold:1e12; % adjust the condition number threshold
+END;
+INPUT
+ function f,g;
+ variable_group x,y;
+
+ f = y - x^10;
+ g = y - 1e-10;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/HyperbolaParabola.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/HyperbolaParabola.input
new file mode 100644
index 0000000..4ab7b47
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/HyperbolaParabola.input
@@ -0,0 +1,7 @@
+%HyperbolaParabola.input
+ function hyperbola,parabola;
+ variable_group x,y;
+
+ hyperbola = x^2 - y^2 - 1;
+ parabola = x - y^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/HyperbolaParabola_sharpen.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/HyperbolaParabola_sharpen.input
new file mode 100644
index 0000000..dc5bf24
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/HyperbolaParabola_sharpen.input
@@ -0,0 +1,12 @@
+% HyperbolaParabola_sharpen.input
+CONFIG
+ SharpenOnly:1; % use the sharpening module
+ SharpenDigits:20; % sharpen to 20 digits
+END;
+INPUT
+ function hyperbola,parabola;
+ variable_group x,y;
+
+ hyperbola = x^2 - y^2 - 1;
+ parabola = x - y^2 - 1;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/NewtonHomotopy.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/NewtonHomotopy.input
new file mode 100644
index 0000000..2abae6d
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/NewtonHomotopy.input
@@ -0,0 +1,15 @@
+% NewtonHomotopy.input
+CONFIG
+ % Use a Newton homotopy to sharpen
+ ParameterHomotopy:2;
+ FinalTol:1e-20;
+END;
+INPUT
+ function parabola,twolines
+ variable_group x,y;
+ parameter t,x0,y0;
+ random gamma;
+
+ parabola = (1-t+gamma*t)*(y - x^2) - gamma*t*(y0 - x0^2);
+ twolines = (1-t+gamma*t)*(x^2 - y^2) - gamma*t*(x0^2 - y0^2);
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/RoundingError.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/RoundingError.input
new file mode 100644
index 0000000..1f22cbf
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/RoundingError.input
@@ -0,0 +1,12 @@
+% RoundingError.input
+ function f1,f2;
+ variable_group x;
+ variable_group y;
+ constant a,b;
+
+ a = 1.414214; % round sqrt(2) to 6 decimal places
+ b = 2;
+
+ f1 = x*y^3 - a*y^3 - 1;
+ f2 = x^2 - b;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/ScaledSystem.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/ScaledSystem.input
new file mode 100644
index 0000000..e03ad8a
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/ScaledSystem.input
@@ -0,0 +1,11 @@
+% ScaledSystem.input
+CONFIG
+ SharpenDigits:30; % sharpen endpoints to 30 digits
+END;
+INPUT
+ function f1,f2;
+ variable_group hatx,haty;
+
+ f1 = hatx*haty - 1;
+ f2 = hatx - haty - 10;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/SharpenDigits.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/SharpenDigits.input
new file mode 100644
index 0000000..d095e07
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/SharpenDigits.input
@@ -0,0 +1,12 @@
+% SharpenDigits.input
+CONFIG
+ % Solve using a total-degree homotopy
+ SharpenDigits:20; % sharpen the endpoints to 20 digits
+END;
+INPUT
+ function circle,parabola;
+ variable_group x,y;
+
+ circle = x^2 + (y-1)^2 - 1;
+ parabola = y - 2*x^2;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/Unscale.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/Unscale.input
new file mode 100644
index 0000000..c3c68c3
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/Unscale.input
@@ -0,0 +1,14 @@
+% Unscale.input
+CONFIG
+ TrackType:-4; % perform evaluation
+ % Utilize 96-bit fixed precision
+ MPType:1;
+ Precision:96;
+END;
+INPUT
+ function x,y;
+ variable_group hatx,haty;
+
+ x = 1e-11*hatx;
+ y = 1e-5*haty;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_NewtonHomotopy.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_NewtonHomotopy.input
new file mode 100644
index 0000000..ec7e33f
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_NewtonHomotopy.input
@@ -0,0 +1,14 @@
+% UserDefined_NewtonHomotopy.input
+CONFIG
+ % Track a user-defined homotopy
+ UserHomotopy:1;
+END;
+INPUT
+ function f;
+ variable x;
+ pathvariable T;
+ parameter t;
+ t = T;
+
+ f = exp(sin(x/(1+x))) + 1/cos(x-2) - 1 - t*(-1.81713970082);
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_ProductSpace.input b/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_ProductSpace.input
new file mode 100644
index 0000000..242b7f5
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_ProductSpace.input
@@ -0,0 +1,19 @@
+% UserDefined_ProductSpace.input
+CONFIG
+ % Track a user-defined homotopy on a product space
+ UserHomotopy:2;
+ SecurityLevel:1;
+END;
+INPUT
+ function f,g;
+ variable_group x;
+ variable_group y;
+ pathvariable T;
+ t = 1-T; % t goes from 0 to 1
+ parameter a,b;
+ a = sin(t*Pi/2);
+ b = t;
+
+ f = x^2 - 3*a*x - 4;
+ g = x*y + y - b;
+END;
diff --git a/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_ProductSpace.start b/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_ProductSpace.start
new file mode 100644
index 0000000..becc88a
--- /dev/null
+++ b/test/data/Bertini_examples/Chap7AdvancedIsolated/UserDefined_ProductSpace.start
@@ -0,0 +1,8 @@
+2
+
+2 0
+0 0
+
+-2 0
+0 0
+% UserDefined_ProductSpace.start
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/._.DS_Store b/test/data/Bertini_examples/Chap8PositiveDimensional/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap8PositiveDimensional/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/BricardSixR.input b/test/data/Bertini_examples/Chap8PositiveDimensional/BricardSixR.input
new file mode 100644
index 0000000..27c442e
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/BricardSixR.input
@@ -0,0 +1,80 @@
+% Bricard 6R (six-revolute) mechanism
+%
+% This is a special case of 6R serial-link inverse kinematics.
+% This closed-loop 6R mechanism has a 1-degree-of-freedom motion,
+% so we use TrackType:1 to find that curve.
+%
+CONFIG
+ TrackType:1;
+END;
+
+INPUT
+ % link lengths
+ constant a1,a2,a3,a4,a5;
+ % link offsets
+ constant d2,d3,d4,d5;
+ % twist cosines
+ constant c1,c2,c3,c4,c5;
+ % endpoint position
+ constant px,py,pz;
+ % joint 1 orientation (fixed)
+ constant z1x,z1y,z1z;
+ % joint 6 orientation (fixed)
+ constant z6x,z6y,z6z;
+
+ % give values to constants
+ z1x=1; z1y=0; z1z=0;
+ z6x=0; z6y=0; z6z=1;
+ a1=1; a2=1; a3=1; a4=1; a5=1;
+ d2=0; d3=0; d4=0; d5=0;
+ c1=0; c2=0; c3=0; c4=0; c5=0;
+ px=0; py=1; pz=0;
+
+ variable_group z2x,z2y,z2z, z3x,z3y,z3z, z4x,z4y,z4z, z5x,z5y,z5z;
+
+ function unit2, unit3, unit4, unit5;
+ function twist1, twist2, twist3, twist4, twist5;
+ function X,Y,Z;
+
+ unit2 = z2x^2 + z2y^2 + z2z^2 -1;
+ unit3 = z3x^2 + z3y^2 + z3z^2 -1;
+ unit4 = z4x^2 + z4y^2 + z4z^2 -1;
+ unit5 = z5x^2 + z5y^2 + z5z^2 -1;
+ twist1 = z1x*z2x + z1y*z2y + z1z*z2z - c1;
+ twist2 = z2x*z3x + z2y*z3y + z2z*z3z - c2;
+ twist3 = z3x*z4x + z3y*z4y + z3z*z4z - c3;
+ twist4 = z4x*z5x + z4y*z5y + z4z*z5z - c4;
+ twist5 = z5x*z6x + z5y*z6y + z5z*z6z - c5;
+ % form cross products
+ x1x = z1y*z2z - z1z*z2y;
+ x2x = z2y*z3z - z2z*z3y;
+ x3x = z3y*z4z - z3z*z4y;
+ x4x = z4y*z5z - z4z*z5y;
+ x5x = z5y*z6z - z5z*z6y;
+ x1y = z1z*z2x - z1x*z2z;
+ x2y = z2z*z3x - z2x*z3z;
+ x3y = z3z*z4x - z3x*z4z;
+ x4y = z4z*z5x - z4x*z5z;
+ x5y = z5z*z6x - z5x*z6z;
+ x1z = z1x*z2y - z1y*z2x;
+ x2z = z2x*z3y - z2y*z3x;
+ x3z = z3x*z4y - z3y*z4x;
+ x4z = z4x*z5y - z4y*z5x;
+ x5z = z5x*z6y - z5y*z6x;
+ % position
+ X = a1*x1x + d2*z2x +
+ a2*x2x + d3*z3x +
+ a3*x3x + d4*z4x +
+ a4*x4x + d5*z5x +
+ a5*x5x - px;
+ Y = a1*x1y + d2*z2y +
+ a2*x2y + d3*z3y +
+ a3*x3y + d4*z4y +
+ a4*x4y + d5*z5y +
+ a5*x5y - py;
+ Z = a1*x1z + d2*z2z +
+ a2*x2z + d3*z3z +
+ a3*x3z + d4*z4z +
+ a4*x4z + d5*z5z +
+ a5*x5z - pz;
+END;
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffy.input b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffy.input
new file mode 100644
index 0000000..409d018
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffy.input
@@ -0,0 +1,152 @@
+% Bertini file for Griffis-Duffy platform forward kinematics
+%
+% This is the general Griffis-Duffy, special case of Stewart-Gough
+%
+% We modify the general Stewart-Gough system to put the parameters
+% on the Griffis-Duffy parameter space.
+CONFIG
+ TrackType:1;
+END
+
+INPUT
+ % Base & moving platforms are both triangles with joints
+ % at vertices and one joint along each edge.
+ % Specify this by giving random vertices and then
+ % interpolating to put random point on each edge.
+ % As the figures are planar, we set z-coordinates to zero.
+ % Vertices for the stationary rigid body
+ random a1x,a1y, a3x,a3y, a5x,a5y;
+ constant a1z,a2z,a3z,a4z,a5z,a6z;
+ a1z=0;a2z=0;a3z=0;a4z=0;a5z=0;a6z=0;
+ % Interpolating constants for sides
+ random a2,a4,a6;
+ a2x = a2*a1x + (1-a2)*a3x;
+ a2y = a2*a1y + (1-a2)*a3y;
+ a4x = a4*a3x + (1-a4)*a5x;
+ a4y = a4*a3y + (1-a4)*a5y;
+ a6x = a6*a5x + (1-a6)*a1x;
+ a6y = a6*a5y + (1-a6)*a1y;
+ % Do similar for the moving rigid body
+ % Vertices for the stationary rigid body
+ random b2x,b2y, b4x,b4y, b6x,b6y;
+ constant b1z,b2z,b3z,b4z,b5z,b6z;
+ b1z=0;b2z=0;b3z=0;b4z=0;b5z=0;b6z=0;
+ % Interpolating constants for sides
+ random b1,b3,b5;
+ b1x = b1*b6x + (1-b1)*b2x;
+ b1y = b1*b6y + (1-b1)*b2y;
+ b3x = b3*b2x + (1-b3)*b4x;
+ b3y = b3*b2y + (1-b3)*b4y;
+ b5x = b5*b4x + (1-b5)*b6x;
+ b5y = b5*b4y + (1-b5)*b6y;
+ % squared distances between point pairs
+ random d1,d2,d3,d4,d5,d6;
+ %
+
+ % These will be the squared distance functions
+ function f1,f2,f3,f4,f5,f6;
+ % The Study quadric
+ function Study;
+
+ % Use Study coordinates for the position & orientation of the moving body.
+ hom_variable_group e0,e1,e2,e3,g0,g1,g2,g3;
+
+ % Let X be the 4x4 representation of quaternion (x0,x1,x2,x3)
+ % So
+ % X = [ x0 -x1 -x2 -x3
+ % x1 x0 -x3 x2
+ % x2 x3 x0 -x1
+ % x3 -x2 x1 x0 ]
+ % Treat vector (v1,v2,v3) as quaternion (0,v1,v2,v3).
+ % We also say that Re(x) = x0 or equivalently, Re(X) = x0*I.
+
+ % Quaternions obey the relation X*X' = |(x0,x1,x2,x3)|^2 = |X|^2
+ % Let ee = E*E', gg = G*G':
+ ee = e0^2 + e1^2 + e2^2 +e3^2;
+ gg = g0^2 + g1^2 + g2^2 +g3^2;
+
+ % After transformation, a point b = (b1,b2,b3) becomes
+ % Transf(b) = (E*B*E' + G*E')/ee
+ % with the Study quadric side condition of
+ % Study = Re(G*E') = 0
+ Study = g0*e0 + g1*e1 + g2*e2 + g3*e3;
+
+ % Accordingly, the governing equations are the squared distance relations
+ % (*) d = | (E*B*E' + G*E')/ee - A |^2
+ % = [ (E*B*E' + G*E')/ee - A ]*[ (E*B'*E' + E*G')/ee - A']
+ % After expanding this, several instances of E*E' = ee*I appear. After
+ % simplifying ee/ee = 1 (cases of ee=0 are meaningless) and then
+ % clearing the denominator by multiplying by ee, (*) becomes
+ % a quadric relation in E,G, with A,B,d considered constants.
+ % We apply this 6 times for d_i, a_i, b_i.
+
+ % We simplify (*) with some vector algebra, where the following
+ % terms appear:
+ R11 = e0^2+e1^2-e2^2-e3^2;
+ R12 = 2*(-e0*e3+e1*e2);
+ R13 = 2*( e0*e2+e1*e3);
+ R21 = 2*( e0*e3+e2*e1);
+ R22 = e0^2-e1^2+e2^2-e3^2;
+ R23 = 2*(-e0*e1+e2*e3);
+ R31 = 2*(-e0*e2+e3*e1);
+ R32 = 2*( e0*e1+e3*e2);
+ R33 = e0^2-e1^2-e2^2+e3^2;
+ u1 = g0*e1 - e0*g1;
+ u2 = g0*e2 - e0*g2;
+ u3 = g0*e3 - e0*g3;
+ v1 = g2*e3 - g3*e2;
+ v2 = g3*e1 - g1*e3;
+ v3 = g1*e2 - g2*e1;
+
+ % Now, we form the 6 distance equations.
+ % Write it in terms of J, then substitute J = 1,...,6
+% fJ = (aJx^2+aJy^2+aJz^2+bJx^2+bJy^2+bJz^2-dJ)*ee + gg +
+% 2*(u1*(aJx-bJx) + u2*(aJy-bJy) + u3*(aJz-bJz)) +
+% 2*(v1*(aJx+bJx) + v2*(aJy+bJy) + v3*(aJz+bJz)) +
+% -2*( aJx*(R11*bJx+R12*bJy+R13*bJz) +
+% aJy*(R21*bJx+R22*bJy+R23*bJz) +
+% aJz*(R31*bJx+R32*bJy+R33*bJz) ) ;
+
+ f1 = (a1x^2+a1y^2+a1z^2+b1x^2+b1y^2+b1z^2-d1)*ee + gg +
+ 2*(u1*(a1x-b1x) + u2*(a1y-b1y) + u3*(a1z-b1z)) +
+ 2*(v1*(a1x+b1x) + v2*(a1y+b1y) + v3*(a1z+b1z)) +
+ -2*( a1x*(R11*b1x+R12*b1y+R13*b1z) +
+ a1y*(R21*b1x+R22*b1y+R23*b1z) +
+ a1z*(R31*b1x+R32*b1y+R33*b1z) ) ;
+
+ f2 = (a2x^2+a2y^2+a2z^2+b2x^2+b2y^2+b2z^2-d2)*ee + gg +
+ 2*(u1*(a2x-b2x) + u2*(a2y-b2y) + u3*(a2z-b2z)) +
+ 2*(v1*(a2x+b2x) + v2*(a2y+b2y) + v3*(a2z+b2z)) +
+ -2*( a2x*(R11*b2x+R12*b2y+R13*b2z) +
+ a2y*(R21*b2x+R22*b2y+R23*b2z) +
+ a2z*(R31*b2x+R32*b2y+R33*b2z) ) ;
+
+ f3 = (a3x^2+a3y^2+a3z^2+b3x^2+b3y^2+b3z^2-d3)*ee + gg +
+ 2*(u1*(a3x-b3x) + u2*(a3y-b3y) + u3*(a3z-b3z)) +
+ 2*(v1*(a3x+b3x) + v2*(a3y+b3y) + v3*(a3z+b3z)) +
+ -2*( a3x*(R11*b3x+R12*b3y+R13*b3z) +
+ a3y*(R21*b3x+R22*b3y+R23*b3z) +
+ a3z*(R31*b3x+R32*b3y+R33*b3z) ) ;
+
+ f4 = (a4x^2+a4y^2+a4z^2+b4x^2+b4y^2+b4z^2-d4)*ee + gg +
+ 2*(u1*(a4x-b4x) + u2*(a4y-b4y) + u3*(a4z-b4z)) +
+ 2*(v1*(a4x+b4x) + v2*(a4y+b4y) + v3*(a4z+b4z)) +
+ -2*( a4x*(R11*b4x+R12*b4y+R13*b4z) +
+ a4y*(R21*b4x+R22*b4y+R23*b4z) +
+ a4z*(R31*b4x+R32*b4y+R33*b4z) ) ;
+
+ f5 = (a5x^2+a5y^2+a5z^2+b5x^2+b5y^2+b5z^2-d5)*ee + gg +
+ 2*(u1*(a5x-b5x) + u2*(a5y-b5y) + u3*(a5z-b5z)) +
+ 2*(v1*(a5x+b5x) + v2*(a5y+b5y) + v3*(a5z+b5z)) +
+ -2*( a5x*(R11*b5x+R12*b5y+R13*b5z) +
+ a5y*(R21*b5x+R22*b5y+R23*b5z) +
+ a5z*(R31*b5x+R32*b5y+R33*b5z) ) ;
+
+ f6 = (a6x^2+a6y^2+a6z^2+b6x^2+b6y^2+b6z^2-d6)*ee + gg +
+ 2*(u1*(a6x-b6x) + u2*(a6y-b6y) + u3*(a6z-b6z)) +
+ 2*(v1*(a6x+b6x) + v2*(a6y+b6y) + v3*(a6z+b6z)) +
+ -2*( a6x*(R11*b6x+R12*b6y+R13*b6z) +
+ a6y*(R21*b6x+R22*b6y+R23*b6z) +
+ a6z*(R31*b6x+R32*b6y+R33*b6z) ) ;
+
+END
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyFoldable.input b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyFoldable.input
new file mode 100644
index 0000000..eb3d1e7
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyFoldable.input
@@ -0,0 +1,167 @@
+% Bertini file for Foldable Griffis-Duffy Type platform forward kinematics
+%
+% This special case of Stewart-Gough is Griffis-Duffy with
+% base & moving triangles as equilateral and congruent, with joints at
+% vertices and midpoints. Leg lengths all equal to altitude of
+% triangles
+%
+% We modify the general Stewart-Gough system to put the parameters
+% on the Griffis-Duffy parameter space.
+CONFIG
+ TrackType:1;
+END
+
+INPUT
+ % Base & moving platforms are both triangles with joints
+ % at vertices and one joint along each edge.
+ % Specify this by giving random vertices and then
+ % interpolating to put random point on each edge.
+ % As the figures are planar, we set z-coordinates to zero.
+ constant sqrt3;
+ sqrt3 = 3^(1/2);
+ % Vertices for the stationary rigid body
+ constant a1x,a1y, a3x,a3y, a5x,a5y;
+ a1x = -sqrt3; a1y = -1;
+ a3x = sqrt3; a3y = -1;
+ a5x = 0; a5y = 2;
+ constant a1z,a2z,a3z,a4z,a5z,a6z;
+ a1z=0;a2z=0;a3z=0;a4z=0;a5z=0;a6z=0;
+ % Interpolating constants for sides
+ constant a2,a4,a6;
+ a2=0.5;a4=0.5;a6=0.5;
+ a2x = a2*a1x + (1-a2)*a3x;
+ a2y = a2*a1y + (1-a2)*a3y;
+ a4x = a4*a3x + (1-a4)*a5x;
+ a4y = a4*a3y + (1-a4)*a5y;
+ a6x = a6*a5x + (1-a6)*a1x;
+ a6y = a6*a5y + (1-a6)*a1y;
+ % Do similar for the moving rigid body
+ % Vertices for the stationary rigid body
+ constant b2x,b2y, b4x,b4y, b6x,b6y;
+ b2x = 0; b2y=2;
+ b4x = -sqrt3; b4y = -1;
+ b6x = sqrt3; b6y = -1;
+ constant b1z,b2z,b3z,b4z,b5z,b6z;
+ b1z=0;b2z=0;b3z=0;b4z=0;b5z=0;b6z=0;
+ % Interpolating constants for sides
+ constant b1,b3,b5;
+ b1=0.5;b3=0.5;b5=0.5;
+ b1x = b1*b6x + (1-b1)*b2x;
+ b1y = b1*b6y + (1-b1)*b2y;
+ b3x = b3*b2x + (1-b3)*b4x;
+ b3y = b3*b2y + (1-b3)*b4y;
+ b5x = b5*b4x + (1-b5)*b6x;
+ b5y = b5*b4y + (1-b5)*b6y;
+ % squared distances between point pairs
+ constant d1;
+ d1=9;
+ d2=d1;d3=d1;d4=d1;d5=d1;d6=d1;
+ %
+
+ % These will be the squared distance functions
+ function f1,f2,f3,f4,f5,f6;
+ % The Study quadric
+ function Study;
+
+ % Use Study coordinates for the position & orientation of the moving body.
+ hom_variable_group e0,e1,e2,e3,g0,g1,g2,g3;
+
+ % Let X be the 4x4 representation of quaternion (x0,x1,x2,x3)
+ % So
+ % X = [ x0 -x1 -x2 -x3
+ % x1 x0 -x3 x2
+ % x2 x3 x0 -x1
+ % x3 -x2 x1 x0 ]
+ % Treat vector (v1,v2,v3) as quaternion (0,v1,v2,v3).
+ % We also say that Re(x) = x0 or equivalently, Re(X) = x0*I.
+
+ % Quaternions obey the relation X*X' = |(x0,x1,x2,x3)|^2 = |X|^2
+ % Let ee = E*E', gg = G*G':
+ ee = e0^2 + e1^2 + e2^2 +e3^2;
+ gg = g0^2 + g1^2 + g2^2 +g3^2;
+
+ % After transformation, a point b = (b1,b2,b3) becomes
+ % Transf(b) = (E*B*E' + G*E')/ee
+ % with the Study quadric side condition of
+ % Study = Re(G*E') = 0
+ Study = g0*e0 + g1*e1 + g2*e2 + g3*e3;
+
+ % Accordingly, the governing equations are the squared distance relations
+ % (*) d = | (E*B*E' + G*E')/ee - A |^2
+ % = [ (E*B*E' + G*E')/ee - A ]*[ (E*B'*E' + E*G')/ee - A']
+ % After expanding this, several instances of E*E' = ee*I appear. After
+ % simplifying ee/ee = 1 (cases of ee=0 are meaningless) and then
+ % clearing the denominator by multiplying by ee, (*) becomes
+ % a quadric relation in E,G, with A,B,d considered constants.
+ % We apply this 6 times for d_i, a_i, b_i.
+
+ % We simplify (*) with some vector algebra, where the following
+ % terms appear:
+ R11 = e0^2+e1^2-e2^2-e3^2;
+ R12 = 2*(-e0*e3+e1*e2);
+ R13 = 2*( e0*e2+e1*e3);
+ R21 = 2*( e0*e3+e2*e1);
+ R22 = e0^2-e1^2+e2^2-e3^2;
+ R23 = 2*(-e0*e1+e2*e3);
+ R31 = 2*(-e0*e2+e3*e1);
+ R32 = 2*( e0*e1+e3*e2);
+ R33 = e0^2-e1^2-e2^2+e3^2;
+ u1 = g0*e1 - e0*g1;
+ u2 = g0*e2 - e0*g2;
+ u3 = g0*e3 - e0*g3;
+ v1 = g2*e3 - g3*e2;
+ v2 = g3*e1 - g1*e3;
+ v3 = g1*e2 - g2*e1;
+
+ % Now, we form the 6 distance equations.
+ % Write it in terms of J, then substitute J = 1,...,6
+% fJ = (aJx^2+aJy^2+aJz^2+bJx^2+bJy^2+bJz^2-dJ)*ee + gg +
+% 2*(u1*(aJx-bJx) + u2*(aJy-bJy) + u3*(aJz-bJz)) +
+% 2*(v1*(aJx+bJx) + v2*(aJy+bJy) + v3*(aJz+bJz)) +
+% -2*( aJx*(R11*bJx+R12*bJy+R13*bJz) +
+% aJy*(R21*bJx+R22*bJy+R23*bJz) +
+% aJz*(R31*bJx+R32*bJy+R33*bJz) ) ;
+
+ f1 = (a1x^2+a1y^2+a1z^2+b1x^2+b1y^2+b1z^2-d1)*ee + gg +
+ 2*(u1*(a1x-b1x) + u2*(a1y-b1y) + u3*(a1z-b1z)) +
+ 2*(v1*(a1x+b1x) + v2*(a1y+b1y) + v3*(a1z+b1z)) +
+ -2*( a1x*(R11*b1x+R12*b1y+R13*b1z) +
+ a1y*(R21*b1x+R22*b1y+R23*b1z) +
+ a1z*(R31*b1x+R32*b1y+R33*b1z) ) ;
+
+ f2 = (a2x^2+a2y^2+a2z^2+b2x^2+b2y^2+b2z^2-d2)*ee + gg +
+ 2*(u1*(a2x-b2x) + u2*(a2y-b2y) + u3*(a2z-b2z)) +
+ 2*(v1*(a2x+b2x) + v2*(a2y+b2y) + v3*(a2z+b2z)) +
+ -2*( a2x*(R11*b2x+R12*b2y+R13*b2z) +
+ a2y*(R21*b2x+R22*b2y+R23*b2z) +
+ a2z*(R31*b2x+R32*b2y+R33*b2z) ) ;
+
+ f3 = (a3x^2+a3y^2+a3z^2+b3x^2+b3y^2+b3z^2-d3)*ee + gg +
+ 2*(u1*(a3x-b3x) + u2*(a3y-b3y) + u3*(a3z-b3z)) +
+ 2*(v1*(a3x+b3x) + v2*(a3y+b3y) + v3*(a3z+b3z)) +
+ -2*( a3x*(R11*b3x+R12*b3y+R13*b3z) +
+ a3y*(R21*b3x+R22*b3y+R23*b3z) +
+ a3z*(R31*b3x+R32*b3y+R33*b3z) ) ;
+
+ f4 = (a4x^2+a4y^2+a4z^2+b4x^2+b4y^2+b4z^2-d4)*ee + gg +
+ 2*(u1*(a4x-b4x) + u2*(a4y-b4y) + u3*(a4z-b4z)) +
+ 2*(v1*(a4x+b4x) + v2*(a4y+b4y) + v3*(a4z+b4z)) +
+ -2*( a4x*(R11*b4x+R12*b4y+R13*b4z) +
+ a4y*(R21*b4x+R22*b4y+R23*b4z) +
+ a4z*(R31*b4x+R32*b4y+R33*b4z) ) ;
+
+ f5 = (a5x^2+a5y^2+a5z^2+b5x^2+b5y^2+b5z^2-d5)*ee + gg +
+ 2*(u1*(a5x-b5x) + u2*(a5y-b5y) + u3*(a5z-b5z)) +
+ 2*(v1*(a5x+b5x) + v2*(a5y+b5y) + v3*(a5z+b5z)) +
+ -2*( a5x*(R11*b5x+R12*b5y+R13*b5z) +
+ a5y*(R21*b5x+R22*b5y+R23*b5z) +
+ a5z*(R31*b5x+R32*b5y+R33*b5z) ) ;
+
+ f6 = (a6x^2+a6y^2+a6z^2+b6x^2+b6y^2+b6z^2-d6)*ee + gg +
+ 2*(u1*(a6x-b6x) + u2*(a6y-b6y) + u3*(a6z-b6z)) +
+ 2*(v1*(a6x+b6x) + v2*(a6y+b6y) + v3*(a6z+b6z)) +
+ -2*( a6x*(R11*b6x+R12*b6y+R13*b6z) +
+ a6y*(R21*b6x+R22*b6y+R23*b6z) +
+ a6z*(R31*b6x+R32*b6y+R33*b6z) ) ;
+
+END
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyI.input b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyI.input
new file mode 100644
index 0000000..548544e
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyI.input
@@ -0,0 +1,173 @@
+% Bertini file for Griffis-Duffy Type I platform forward kinematics
+%
+% This special case of Stewart-Gough is Griffis-Duffy with
+% base & moving triangles as equilateral, with joints at
+% vertices and midpoints. Leg lengths compatible.
+%
+% We modify the general Stewart-Gough system to put the parameters
+% on the Griffis-Duffy parameter space.
+CONFIG
+ TrackType:1;
+END
+
+INPUT
+ % Base & moving platforms are both triangles with joints
+ % at vertices and one joint along each edge.
+ % Specify this by giving random vertices and then
+ % interpolating to put random point on each edge.
+ % As the figures are planar, we set z-coordinates to zero.
+ constant sqrt3;
+ sqrt3 = 3^(1/2);
+ % Vertices for the stationary rigid body
+ constant a1x,a1y, a3x,a3y, a5x,a5y;
+ a1x = -sqrt3; a1y = -1;
+ a3x = sqrt3; a3y = -1;
+ a5x = 0; a5y = 2;
+ constant a1z,a2z,a3z,a4z,a5z,a6z;
+ a1z=0;a2z=0;a3z=0;a4z=0;a5z=0;a6z=0;
+ % Interpolating constants for sides
+ constant a2,a4,a6;
+ a2=0.5;a4=0.5;a6=0.5;
+ a2x = a2*a1x + (1-a2)*a3x;
+ a2y = a2*a1y + (1-a2)*a3y;
+ a4x = a4*a3x + (1-a4)*a5x;
+ a4y = a4*a3y + (1-a4)*a5y;
+ a6x = a6*a5x + (1-a6)*a1x;
+ a6y = a6*a5y + (1-a6)*a1y;
+ % Do similar for the moving rigid body
+ % Vertices for the stationary rigid body, scaling factor rho.
+ constant rho;
+ rho = 0.40848840084869084689607210007511811758273381523777e0 +I*0.43843518180137204471464687496504664346923820863761e0;
+ constant b2x,b2y, b4x,b4y, b6x,b6y;
+ b2x = 0; b2y=rho*2;
+ b4x = -rho*sqrt3; b4y = -rho;
+ b6x = rho*sqrt3; b6y = -rho;
+ constant b1z,b2z,b3z,b4z,b5z,b6z;
+ b1z=0;b2z=0;b3z=0;b4z=0;b5z=0;b6z=0;
+ % Interpolating constants for sides
+ constant b1,b3,b5;
+ b1=0.5;b3=0.5;b5=0.5;
+ b1x = b1*b6x + (1-b1)*b2x;
+ b1y = b1*b6y + (1-b1)*b2y;
+ b3x = b3*b2x + (1-b3)*b4x;
+ b3y = b3*b2y + (1-b3)*b4y;
+ b5x = b5*b4x + (1-b5)*b6x;
+ b5y = b5*b4y + (1-b5)*b6y;
+ % squared distances between point pairs
+ constant d1,d2,d3,d4,d5,d6;
+ d1= 0.60253285154416311666763946757947656005254767936440e1 +I*0.46244460773969870774591688042239016441342159529488e1;
+ d2= 0.68195377486446525775410545489180535494469537475256e0 +I*0.22337719013829322825025502032123983328376923876513e1;
+ d3= 0.33100335856880728115480859653452549775233437122361e1 +I*-0.17966811115594162795869439796591218630615640979776e1;
+ d4= 0.15579139233250532088351660739114320197236432225561e1 +I*0.29335247385730361447386332238267248559416170233522e1;
+ d5= 0.40898037844000270035640955828371496115912598858697e1 +I*0.22349953092285726839281624652249023930268956704736e1;
+ d6= 0.19570344722206797029694886155922008947671975753046e1 +I*0.31191859883274302363997819325785667988053249319080e1;
+
+ %
+
+ % These will be the squared distance functions
+ function f1,f2,f3,f4,f5,f6;
+ % The Study quadric
+ function Study;
+
+ % Use Study coordinates for the position & orientation of the moving body.
+ hom_variable_group e0,e1,e2,e3,g0,g1,g2,g3;
+
+ % Let X be the 4x4 representation of quaternion (x0,x1,x2,x3)
+ % So
+ % X = [ x0 -x1 -x2 -x3
+ % x1 x0 -x3 x2
+ % x2 x3 x0 -x1
+ % x3 -x2 x1 x0 ]
+ % Treat vector (v1,v2,v3) as quaternion (0,v1,v2,v3).
+ % We also say that Re(x) = x0 or equivalently, Re(X) = x0*I.
+
+ % Quaternions obey the relation X*X' = |(x0,x1,x2,x3)|^2 = |X|^2
+ % Let ee = E*E', gg = G*G':
+ ee = e0^2 + e1^2 + e2^2 +e3^2;
+ gg = g0^2 + g1^2 + g2^2 +g3^2;
+
+ % After transformation, a point b = (b1,b2,b3) becomes
+ % Transf(b) = (E*B*E' + G*E')/ee
+ % with the Study quadric side condition of
+ % Study = Re(G*E') = 0
+ Study = g0*e0 + g1*e1 + g2*e2 + g3*e3;
+
+ % Accordingly, the governing equations are the squared distance relations
+ % (*) d = | (E*B*E' + G*E')/ee - A |^2
+ % = [ (E*B*E' + G*E')/ee - A ]*[ (E*B'*E' + E*G')/ee - A']
+ % After expanding this, several instances of E*E' = ee*I appear. After
+ % simplifying ee/ee = 1 (cases of ee=0 are meaningless) and then
+ % clearing the denominator by multiplying by ee, (*) becomes
+ % a quadric relation in E,G, with A,B,d considered constants.
+ % We apply this 6 times for d_i, a_i, b_i.
+
+ % We simplify (*) with some vector algebra, where the following
+ % terms appear:
+ R11 = e0^2+e1^2-e2^2-e3^2;
+ R12 = 2*(-e0*e3+e1*e2);
+ R13 = 2*( e0*e2+e1*e3);
+ R21 = 2*( e0*e3+e2*e1);
+ R22 = e0^2-e1^2+e2^2-e3^2;
+ R23 = 2*(-e0*e1+e2*e3);
+ R31 = 2*(-e0*e2+e3*e1);
+ R32 = 2*( e0*e1+e3*e2);
+ R33 = e0^2-e1^2-e2^2+e3^2;
+ u1 = g0*e1 - e0*g1;
+ u2 = g0*e2 - e0*g2;
+ u3 = g0*e3 - e0*g3;
+ v1 = g2*e3 - g3*e2;
+ v2 = g3*e1 - g1*e3;
+ v3 = g1*e2 - g2*e1;
+
+ % Now, we form the 6 distance equations.
+ % Write it in terms of J, then substitute J = 1,...,6
+% fJ = (aJx^2+aJy^2+aJz^2+bJx^2+bJy^2+bJz^2-dJ)*ee + gg +
+% 2*(u1*(aJx-bJx) + u2*(aJy-bJy) + u3*(aJz-bJz)) +
+% 2*(v1*(aJx+bJx) + v2*(aJy+bJy) + v3*(aJz+bJz)) +
+% -2*( aJx*(R11*bJx+R12*bJy+R13*bJz) +
+% aJy*(R21*bJx+R22*bJy+R23*bJz) +
+% aJz*(R31*bJx+R32*bJy+R33*bJz) ) ;
+
+ f1 = (a1x^2+a1y^2+a1z^2+b1x^2+b1y^2+b1z^2-d1)*ee + gg +
+ 2*(u1*(a1x-b1x) + u2*(a1y-b1y) + u3*(a1z-b1z)) +
+ 2*(v1*(a1x+b1x) + v2*(a1y+b1y) + v3*(a1z+b1z)) +
+ -2*( a1x*(R11*b1x+R12*b1y+R13*b1z) +
+ a1y*(R21*b1x+R22*b1y+R23*b1z) +
+ a1z*(R31*b1x+R32*b1y+R33*b1z) ) ;
+
+ f2 = (a2x^2+a2y^2+a2z^2+b2x^2+b2y^2+b2z^2-d2)*ee + gg +
+ 2*(u1*(a2x-b2x) + u2*(a2y-b2y) + u3*(a2z-b2z)) +
+ 2*(v1*(a2x+b2x) + v2*(a2y+b2y) + v3*(a2z+b2z)) +
+ -2*( a2x*(R11*b2x+R12*b2y+R13*b2z) +
+ a2y*(R21*b2x+R22*b2y+R23*b2z) +
+ a2z*(R31*b2x+R32*b2y+R33*b2z) ) ;
+
+ f3 = (a3x^2+a3y^2+a3z^2+b3x^2+b3y^2+b3z^2-d3)*ee + gg +
+ 2*(u1*(a3x-b3x) + u2*(a3y-b3y) + u3*(a3z-b3z)) +
+ 2*(v1*(a3x+b3x) + v2*(a3y+b3y) + v3*(a3z+b3z)) +
+ -2*( a3x*(R11*b3x+R12*b3y+R13*b3z) +
+ a3y*(R21*b3x+R22*b3y+R23*b3z) +
+ a3z*(R31*b3x+R32*b3y+R33*b3z) ) ;
+
+ f4 = (a4x^2+a4y^2+a4z^2+b4x^2+b4y^2+b4z^2-d4)*ee + gg +
+ 2*(u1*(a4x-b4x) + u2*(a4y-b4y) + u3*(a4z-b4z)) +
+ 2*(v1*(a4x+b4x) + v2*(a4y+b4y) + v3*(a4z+b4z)) +
+ -2*( a4x*(R11*b4x+R12*b4y+R13*b4z) +
+ a4y*(R21*b4x+R22*b4y+R23*b4z) +
+ a4z*(R31*b4x+R32*b4y+R33*b4z) ) ;
+
+ f5 = (a5x^2+a5y^2+a5z^2+b5x^2+b5y^2+b5z^2-d5)*ee + gg +
+ 2*(u1*(a5x-b5x) + u2*(a5y-b5y) + u3*(a5z-b5z)) +
+ 2*(v1*(a5x+b5x) + v2*(a5y+b5y) + v3*(a5z+b5z)) +
+ -2*( a5x*(R11*b5x+R12*b5y+R13*b5z) +
+ a5y*(R21*b5x+R22*b5y+R23*b5z) +
+ a5z*(R31*b5x+R32*b5y+R33*b5z) ) ;
+
+ f6 = (a6x^2+a6y^2+a6z^2+b6x^2+b6y^2+b6z^2-d6)*ee + gg +
+ 2*(u1*(a6x-b6x) + u2*(a6y-b6y) + u3*(a6z-b6z)) +
+ 2*(v1*(a6x+b6x) + v2*(a6y+b6y) + v3*(a6z+b6z)) +
+ -2*( a6x*(R11*b6x+R12*b6y+R13*b6z) +
+ a6y*(R21*b6x+R22*b6y+R23*b6z) +
+ a6z*(R31*b6x+R32*b6y+R33*b6z) ) ;
+
+END
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyII.input b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyII.input
new file mode 100644
index 0000000..45daba5
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyII.input
@@ -0,0 +1,165 @@
+% Bertini file for Griffis-Duffy Type II platform forward kinematics
+%
+% This special case of Stewart-Gough is Griffis-Duffy with
+% base & moving triangles as equilateral and congruent, with joints at
+% vertices and midpoints. Leg lengths all equal.
+%
+% We modify the general Stewart-Gough system to put the parameters
+% on the Griffis-Duffy parameter space.
+CONFIG
+ TrackType:1;
+END
+
+INPUT
+ % Base & moving platforms are both triangles with joints
+ % at vertices and one joint along each edge.
+ % Specify this by giving random vertices and then
+ % interpolating to put random point on each edge.
+ % As the figures are planar, we set z-coordinates to zero.
+ constant sqrt3;
+ sqrt3 = 3^(1/2);
+ % Vertices for the stationary rigid body
+ constant a1x,a1y, a3x,a3y, a5x,a5y;
+ a1x = -sqrt3; a1y = -1;
+ a3x = sqrt3; a3y = -1;
+ a5x = 0; a5y = 2;
+ constant a1z,a2z,a3z,a4z,a5z,a6z;
+ a1z=0;a2z=0;a3z=0;a4z=0;a5z=0;a6z=0;
+ % Interpolating constants for sides
+ constant a2,a4,a6;
+ a2=0.5;a4=0.5;a6=0.5;
+ a2x = a2*a1x + (1-a2)*a3x;
+ a2y = a2*a1y + (1-a2)*a3y;
+ a4x = a4*a3x + (1-a4)*a5x;
+ a4y = a4*a3y + (1-a4)*a5y;
+ a6x = a6*a5x + (1-a6)*a1x;
+ a6y = a6*a5y + (1-a6)*a1y;
+ % Do similar for the moving rigid body
+ % Vertices for the stationary rigid body
+ constant b2x,b2y, b4x,b4y, b6x,b6y;
+ b2x = 0; b2y=2;
+ b4x = -sqrt3; b4y = -1;
+ b6x = sqrt3; b6y = -1;
+ constant b1z,b2z,b3z,b4z,b5z,b6z;
+ b1z=0;b2z=0;b3z=0;b4z=0;b5z=0;b6z=0;
+ % Interpolating constants for sides
+ constant b1,b3,b5;
+ b1=0.5;b3=0.5;b5=0.5;
+ b1x = b1*b6x + (1-b1)*b2x;
+ b1y = b1*b6y + (1-b1)*b2y;
+ b3x = b3*b2x + (1-b3)*b4x;
+ b3y = b3*b2y + (1-b3)*b4y;
+ b5x = b5*b4x + (1-b5)*b6x;
+ b5y = b5*b4y + (1-b5)*b6y;
+ % squared distances between point pairs
+ random d1;
+ d2=d1;d3=d1;d4=d1;d5=d1;d6=d1;
+ %
+
+ % These will be the squared distance functions
+ function f1,f2,f3,f4,f5,f6;
+ % The Study quadric
+ function Study;
+
+ % Use Study coordinates for the position & orientation of the moving body.
+ hom_variable_group e0,e1,e2,e3,g0,g1,g2,g3;
+
+ % Let X be the 4x4 representation of quaternion (x0,x1,x2,x3)
+ % So
+ % X = [ x0 -x1 -x2 -x3
+ % x1 x0 -x3 x2
+ % x2 x3 x0 -x1
+ % x3 -x2 x1 x0 ]
+ % Treat vector (v1,v2,v3) as quaternion (0,v1,v2,v3).
+ % We also say that Re(x) = x0 or equivalently, Re(X) = x0*I.
+
+ % Quaternions obey the relation X*X' = |(x0,x1,x2,x3)|^2 = |X|^2
+ % Let ee = E*E', gg = G*G':
+ ee = e0^2 + e1^2 + e2^2 +e3^2;
+ gg = g0^2 + g1^2 + g2^2 +g3^2;
+
+ % After transformation, a point b = (b1,b2,b3) becomes
+ % Transf(b) = (E*B*E' + G*E')/ee
+ % with the Study quadric side condition of
+ % Study = Re(G*E') = 0
+ Study = g0*e0 + g1*e1 + g2*e2 + g3*e3;
+
+ % Accordingly, the governing equations are the squared distance relations
+ % (*) d = | (E*B*E' + G*E')/ee - A |^2
+ % = [ (E*B*E' + G*E')/ee - A ]*[ (E*B'*E' + E*G')/ee - A']
+ % After expanding this, several instances of E*E' = ee*I appear. After
+ % simplifying ee/ee = 1 (cases of ee=0 are meaningless) and then
+ % clearing the denominator by multiplying by ee, (*) becomes
+ % a quadric relation in E,G, with A,B,d considered constants.
+ % We apply this 6 times for d_i, a_i, b_i.
+
+ % We simplify (*) with some vector algebra, where the following
+ % terms appear:
+ R11 = e0^2+e1^2-e2^2-e3^2;
+ R12 = 2*(-e0*e3+e1*e2);
+ R13 = 2*( e0*e2+e1*e3);
+ R21 = 2*( e0*e3+e2*e1);
+ R22 = e0^2-e1^2+e2^2-e3^2;
+ R23 = 2*(-e0*e1+e2*e3);
+ R31 = 2*(-e0*e2+e3*e1);
+ R32 = 2*( e0*e1+e3*e2);
+ R33 = e0^2-e1^2-e2^2+e3^2;
+ u1 = g0*e1 - e0*g1;
+ u2 = g0*e2 - e0*g2;
+ u3 = g0*e3 - e0*g3;
+ v1 = g2*e3 - g3*e2;
+ v2 = g3*e1 - g1*e3;
+ v3 = g1*e2 - g2*e1;
+
+ % Now, we form the 6 distance equations.
+ % Write it in terms of J, then substitute J = 1,...,6
+% fJ = (aJx^2+aJy^2+aJz^2+bJx^2+bJy^2+bJz^2-dJ)*ee + gg +
+% 2*(u1*(aJx-bJx) + u2*(aJy-bJy) + u3*(aJz-bJz)) +
+% 2*(v1*(aJx+bJx) + v2*(aJy+bJy) + v3*(aJz+bJz)) +
+% -2*( aJx*(R11*bJx+R12*bJy+R13*bJz) +
+% aJy*(R21*bJx+R22*bJy+R23*bJz) +
+% aJz*(R31*bJx+R32*bJy+R33*bJz) ) ;
+
+ f1 = (a1x^2+a1y^2+a1z^2+b1x^2+b1y^2+b1z^2-d1)*ee + gg +
+ 2*(u1*(a1x-b1x) + u2*(a1y-b1y) + u3*(a1z-b1z)) +
+ 2*(v1*(a1x+b1x) + v2*(a1y+b1y) + v3*(a1z+b1z)) +
+ -2*( a1x*(R11*b1x+R12*b1y+R13*b1z) +
+ a1y*(R21*b1x+R22*b1y+R23*b1z) +
+ a1z*(R31*b1x+R32*b1y+R33*b1z) ) ;
+
+ f2 = (a2x^2+a2y^2+a2z^2+b2x^2+b2y^2+b2z^2-d2)*ee + gg +
+ 2*(u1*(a2x-b2x) + u2*(a2y-b2y) + u3*(a2z-b2z)) +
+ 2*(v1*(a2x+b2x) + v2*(a2y+b2y) + v3*(a2z+b2z)) +
+ -2*( a2x*(R11*b2x+R12*b2y+R13*b2z) +
+ a2y*(R21*b2x+R22*b2y+R23*b2z) +
+ a2z*(R31*b2x+R32*b2y+R33*b2z) ) ;
+
+ f3 = (a3x^2+a3y^2+a3z^2+b3x^2+b3y^2+b3z^2-d3)*ee + gg +
+ 2*(u1*(a3x-b3x) + u2*(a3y-b3y) + u3*(a3z-b3z)) +
+ 2*(v1*(a3x+b3x) + v2*(a3y+b3y) + v3*(a3z+b3z)) +
+ -2*( a3x*(R11*b3x+R12*b3y+R13*b3z) +
+ a3y*(R21*b3x+R22*b3y+R23*b3z) +
+ a3z*(R31*b3x+R32*b3y+R33*b3z) ) ;
+
+ f4 = (a4x^2+a4y^2+a4z^2+b4x^2+b4y^2+b4z^2-d4)*ee + gg +
+ 2*(u1*(a4x-b4x) + u2*(a4y-b4y) + u3*(a4z-b4z)) +
+ 2*(v1*(a4x+b4x) + v2*(a4y+b4y) + v3*(a4z+b4z)) +
+ -2*( a4x*(R11*b4x+R12*b4y+R13*b4z) +
+ a4y*(R21*b4x+R22*b4y+R23*b4z) +
+ a4z*(R31*b4x+R32*b4y+R33*b4z) ) ;
+
+ f5 = (a5x^2+a5y^2+a5z^2+b5x^2+b5y^2+b5z^2-d5)*ee + gg +
+ 2*(u1*(a5x-b5x) + u2*(a5y-b5y) + u3*(a5z-b5z)) +
+ 2*(v1*(a5x+b5x) + v2*(a5y+b5y) + v3*(a5z+b5z)) +
+ -2*( a5x*(R11*b5x+R12*b5y+R13*b5z) +
+ a5y*(R21*b5x+R22*b5y+R23*b5z) +
+ a5z*(R31*b5x+R32*b5y+R33*b5z) ) ;
+
+ f6 = (a6x^2+a6y^2+a6z^2+b6x^2+b6y^2+b6z^2-d6)*ee + gg +
+ 2*(u1*(a6x-b6x) + u2*(a6y-b6y) + u3*(a6z-b6z)) +
+ 2*(v1*(a6x+b6x) + v2*(a6y+b6y) + v3*(a6z+b6z)) +
+ -2*( a6x*(R11*b6x+R12*b6y+R13*b6z) +
+ a6y*(R21*b6x+R22*b6y+R23*b6z) +
+ a6z*(R31*b6x+R32*b6y+R33*b6z) ) ;
+
+END
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyILegs.input b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyILegs.input
new file mode 100644
index 0000000..cd78f2b
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/GriffisDuffyILegs.input
@@ -0,0 +1,170 @@
+% Bertini file for Griffis-Duffy Type I platform inverse kinematics
+% This file is used for computing a compatible set of leg lengths.
+%
+% This could be rearranged to use function evaluation for the leg
+% lengths, but since we're just doing it once, we use the same
+% formulas as for forward kinematics. We solve for the squared leg
+% lengths as variables, which appear linearly.
+%
+% This special case of Stewart-Gough is Griffis-Duffy with
+% base & moving triangles as equilateral, with joints at
+% vertices and midpoints. Leg lengths compatible.
+%
+% We modify the general Stewart-Gough system to put the parameters
+% on the Griffis-Duffy parameter space.
+CONFIG
+ FinalTol:1e-40;
+END
+
+INPUT
+ % Base & moving platforms are both triangles with joints
+ % at vertices and one joint along each edge.
+ % Specify this by giving random vertices and then
+ % interpolating to put random point on each edge.
+ % As the figures are planar, we set z-coordinates to zero.
+ constant sqrt3;
+ sqrt3 = 3^(1/2);
+ % Vertices for the stationary rigid body
+ constant a1x,a1y, a3x,a3y, a5x,a5y;
+ a1x = -sqrt3; a1y = -1;
+ a3x = sqrt3; a3y = -1;
+ a5x = 0; a5y = 2;
+ constant a1z,a2z,a3z,a4z,a5z,a6z;
+ a1z=0;a2z=0;a3z=0;a4z=0;a5z=0;a6z=0;
+ % Interpolating constants for sides
+ constant a2,a4,a6;
+ a2=0.5;a4=0.5;a6=0.5;
+ a2x = a2*a1x + (1-a2)*a3x;
+ a2y = a2*a1y + (1-a2)*a3y;
+ a4x = a4*a3x + (1-a4)*a5x;
+ a4y = a4*a3y + (1-a4)*a5y;
+ a6x = a6*a5x + (1-a6)*a1x;
+ a6y = a6*a5y + (1-a6)*a1y;
+ % Do similar for the moving rigid body
+ % Vertices for the stationary rigid body, scaling factor rho.
+ random rho;
+ constant b2x,b2y, b4x,b4y, b6x,b6y;
+ b2x = 0; b2y=rho*2;
+ b4x = -rho*sqrt3; b4y = -rho;
+ b6x = rho*sqrt3; b6y = -rho;
+ constant b1z,b2z,b3z,b4z,b5z,b6z;
+ b1z=0;b2z=0;b3z=0;b4z=0;b5z=0;b6z=0;
+ % Interpolating constants for sides
+ constant b1,b3,b5;
+ b1=0.5;b3=0.5;b5=0.5;
+ b1x = b1*b6x + (1-b1)*b2x;
+ b1y = b1*b6y + (1-b1)*b2y;
+ b3x = b3*b2x + (1-b3)*b4x;
+ b3y = b3*b2y + (1-b3)*b4y;
+ b5x = b5*b4x + (1-b5)*b6x;
+ b5y = b5*b4y + (1-b5)*b6y;
+ % Make a random platform location in Study coordinates
+ random e0,e1,e2,e3,g0,g1,g2;
+
+ % These will be the squared distance functions
+ function f1,f2,f3,f4,f5,f6;
+ % Function to print out rho value
+ function RHO;
+ variable_group r,d1,d2,d3,d4,d5,d6;
+
+ RHO = r-rho;
+
+ % compute g3 to satisfy Study quadric
+ g3 = -(g0*e0 + g1*e1 + g2*e2)/e3;
+
+ % Let X be the 4x4 representation of quaternion (x0,x1,x2,x3)
+ % So
+ % X = [ x0 -x1 -x2 -x3
+ % x1 x0 -x3 x2
+ % x2 x3 x0 -x1
+ % x3 -x2 x1 x0 ]
+ % Treat vector (v1,v2,v3) as quaternion (0,v1,v2,v3).
+ % We also say that Re(x) = x0 or equivalently, Re(X) = x0*I.
+
+ % Quaternions obey the relation X*X' = |(x0,x1,x2,x3)|^2 = |X|^2
+ % Let ee = E*E', gg = G*G':
+ ee = e0^2 + e1^2 + e2^2 +e3^2;
+ gg = g0^2 + g1^2 + g2^2 +g3^2;
+
+ % After transformation, a point b = (b1,b2,b3) becomes
+ % Transf(b) = (E*B*E' + G*E')/ee
+
+ % Accordingly, the governing equations are the squared distance relations
+ % (*) d = | (E*B*E' + G*E')/ee - A |^2
+ % = [ (E*B*E' + G*E')/ee - A ]*[ (E*B'*E' + E*G')/ee - A']
+ % After expanding this, several instances of E*E' = ee*I appear. After
+ % simplifying ee/ee = 1 (cases of ee=0 are meaningless) and then
+ % clearing the denominator by multiplying by ee, (*) becomes
+ % a quadric relation in E,G, with A,B,d considered constants.
+ % We apply this 6 times for d_i, a_i, b_i.
+
+ % We simplify (*) with some vector algebra, where the following
+ % terms appear:
+ R11 = e0^2+e1^2-e2^2-e3^2;
+ R12 = 2*(-e0*e3+e1*e2);
+ R13 = 2*( e0*e2+e1*e3);
+ R21 = 2*( e0*e3+e2*e1);
+ R22 = e0^2-e1^2+e2^2-e3^2;
+ R23 = 2*(-e0*e1+e2*e3);
+ R31 = 2*(-e0*e2+e3*e1);
+ R32 = 2*( e0*e1+e3*e2);
+ R33 = e0^2-e1^2-e2^2+e3^2;
+ u1 = g0*e1 - e0*g1;
+ u2 = g0*e2 - e0*g2;
+ u3 = g0*e3 - e0*g3;
+ v1 = g2*e3 - g3*e2;
+ v2 = g3*e1 - g1*e3;
+ v3 = g1*e2 - g2*e1;
+
+ % Now, we form the 6 distance equations.
+ % Write it in terms of J, then substitute J = 1,...,6
+% fJ = (aJx^2+aJy^2+aJz^2+bJx^2+bJy^2+bJz^2-dJ)*ee + gg +
+% 2*(u1*(aJx-bJx) + u2*(aJy-bJy) + u3*(aJz-bJz)) +
+% 2*(v1*(aJx+bJx) + v2*(aJy+bJy) + v3*(aJz+bJz)) +
+% 2*( aJx*(R11*bJx+R12*bJy+R13*bJz) +
+% aJy*(R21*bJx+R22*bJy+R23*bJz) +
+% aJz*(R31*bJx+R32*bJy+R33*bJz) ) ;
+
+ f1 = (a1x^2+a1y^2+a1z^2+b1x^2+b1y^2+b1z^2-d1)*ee + gg +
+ 2*(u1*(a1x-b1x) + u2*(a1y-b1y) + u3*(a1z-b1z)) +
+ 2*(v1*(a1x+b1x) + v2*(a1y+b1y) + v3*(a1z+b1z)) +
+ 2*( a1x*(R11*b1x+R12*b1y+R13*b1z) +
+ a1y*(R21*b1x+R22*b1y+R23*b1z) +
+ a1z*(R31*b1x+R32*b1y+R33*b1z) ) ;
+
+ f2 = (a2x^2+a2y^2+a2z^2+b2x^2+b2y^2+b2z^2-d2)*ee + gg +
+ 2*(u1*(a2x-b2x) + u2*(a2y-b2y) + u3*(a2z-b2z)) +
+ 2*(v1*(a2x+b2x) + v2*(a2y+b2y) + v3*(a2z+b2z)) +
+ 2*( a2x*(R11*b2x+R12*b2y+R13*b2z) +
+ a2y*(R21*b2x+R22*b2y+R23*b2z) +
+ a2z*(R31*b2x+R32*b2y+R33*b2z) ) ;
+
+ f3 = (a3x^2+a3y^2+a3z^2+b3x^2+b3y^2+b3z^2-d3)*ee + gg +
+ 2*(u1*(a3x-b3x) + u2*(a3y-b3y) + u3*(a3z-b3z)) +
+ 2*(v1*(a3x+b3x) + v2*(a3y+b3y) + v3*(a3z+b3z)) +
+ 2*( a3x*(R11*b3x+R12*b3y+R13*b3z) +
+ a3y*(R21*b3x+R22*b3y+R23*b3z) +
+ a3z*(R31*b3x+R32*b3y+R33*b3z) ) ;
+
+ f4 = (a4x^2+a4y^2+a4z^2+b4x^2+b4y^2+b4z^2-d4)*ee + gg +
+ 2*(u1*(a4x-b4x) + u2*(a4y-b4y) + u3*(a4z-b4z)) +
+ 2*(v1*(a4x+b4x) + v2*(a4y+b4y) + v3*(a4z+b4z)) +
+ 2*( a4x*(R11*b4x+R12*b4y+R13*b4z) +
+ a4y*(R21*b4x+R22*b4y+R23*b4z) +
+ a4z*(R31*b4x+R32*b4y+R33*b4z) ) ;
+
+ f5 = (a5x^2+a5y^2+a5z^2+b5x^2+b5y^2+b5z^2-d5)*ee + gg +
+ 2*(u1*(a5x-b5x) + u2*(a5y-b5y) + u3*(a5z-b5z)) +
+ 2*(v1*(a5x+b5x) + v2*(a5y+b5y) + v3*(a5z+b5z)) +
+ 2*( a5x*(R11*b5x+R12*b5y+R13*b5z) +
+ a5y*(R21*b5x+R22*b5y+R23*b5z) +
+ a5z*(R31*b5x+R32*b5y+R33*b5z) ) ;
+
+ f6 = (a6x^2+a6y^2+a6z^2+b6x^2+b6y^2+b6z^2-d6)*ee + gg +
+ 2*(u1*(a6x-b6x) + u2*(a6y-b6y) + u3*(a6z-b6z)) +
+ 2*(v1*(a6x+b6x) + v2*(a6y+b6y) + v3*(a6z+b6z)) +
+ 2*( a6x*(R11*b6x+R12*b6y+R13*b6z) +
+ a6y*(R21*b6x+R22*b6y+R23*b6z) +
+ a6z*(R31*b6x+R32*b6y+R33*b6z) ) ;
+
+END
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/Illustrative.input b/test/data/Bertini_examples/Chap8PositiveDimensional/Illustrative.input
new file mode 100644
index 0000000..e58ee2b
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/Illustrative.input
@@ -0,0 +1,14 @@
+% Illustrative.input
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ variable_group x,y,z;
+ function f1,f2,f3;
+ S = x^2+y^2+z^2-1;
+ T = y-x^2;
+ U = z-x^3;
+ f1 = T*S*(x-2);
+ f2 = U*S*(y-2);
+ f3 = T*U*S*(z-2);
+END;
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/SmallConstant.input b/test/data/Bertini_examples/Chap8PositiveDimensional/SmallConstant.input
new file mode 100644
index 0000000..73dd65b
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/SmallConstant.input
@@ -0,0 +1,22 @@
+% SmallConstant.input
+%
+% When the constant is bigger than FinalTol, this
+% looks like one irreducible component. But when
+% it is small enough, it is judged to factor into
+% two lines.
+%
+% If the constant really is supposed to be nonzero,
+% the problem should be re-scaled to make this
+% apparent.
+%
+% The default FinalTol is 1e-11. Play with
+% changing FinalTol and the constant to see what
+% happens.
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ variable_group x,y;
+ function f;
+ f = x*y-1e-11;
+END;
diff --git a/test/data/Bertini_examples/Chap8PositiveDimensional/ThreeLines.input b/test/data/Bertini_examples/Chap8PositiveDimensional/ThreeLines.input
new file mode 100644
index 0000000..4f44d8c
--- /dev/null
+++ b/test/data/Bertini_examples/Chap8PositiveDimensional/ThreeLines.input
@@ -0,0 +1,11 @@
+% ThreeLines.input
+CONFIG
+ TrackType:1;
+END;
+INPUT
+ variable_group x,y,z;
+ function f,g;
+
+ f = x*z+y;
+ g = y*z+x;
+END;
diff --git a/test/data/Bertini_examples/Chap9WitnessGeneration/._.DS_Store b/test/data/Bertini_examples/Chap9WitnessGeneration/._.DS_Store
new file mode 100644
index 0000000..460d887
Binary files /dev/null and b/test/data/Bertini_examples/Chap9WitnessGeneration/._.DS_Store differ
diff --git a/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_DimByDim.input b/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_DimByDim.input
new file mode 100644
index 0000000..9f782e7
--- /dev/null
+++ b/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_DimByDim.input
@@ -0,0 +1,20 @@
+% Adjacent Minors dimension-by-dimension
+%
+CONFIG
+ TrackType:1;
+ WitnessGenType:1; % dimension-by-dimension
+ WitnessSupersetOnly:1; % only compute a witness point superset
+END;
+INPUT
+ function f1,f2,f3,f4,f5,f6;
+ variable_group x_[11],x_[12],x_[13],x_[14],
+ x_[21],x_[22],x_[23],x_[24],
+ x_[31],x_[32],x_[33],x_[34];
+
+ f1 = x_[11]*x_[22]-x_[12]*x_[21];
+ f2 = x_[12]*x_[23]-x_[13]*x_[22];
+ f3 = x_[13]*x_[24]-x_[14]*x_[23];
+ f4 = x_[21]*x_[32]-x_[22]*x_[31];
+ f5 = x_[22]*x_[33]-x_[23]*x_[32];
+ f6 = x_[23]*x_[34]-x_[24]*x_[33];
+END;
diff --git a/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_classical.input b/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_classical.input
new file mode 100644
index 0000000..b43bd76
--- /dev/null
+++ b/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_classical.input
@@ -0,0 +1,20 @@
+% Adjacent Minors: witness generation by classical cascade
+%
+CONFIG
+ TrackType:1;
+ WitnessGenType:0; % classical cascade
+ WitnessSupersetOnly:1; % only compute a witness point superset
+END;
+INPUT
+ function f1,f2,f3,f4,f5,f6;
+ variable_group x_[11],x_[12],x_[13],x_[14],
+ x_[21],x_[22],x_[23],x_[24],
+ x_[31],x_[32],x_[33],x_[34];
+
+ f1 = x_[11]*x_[22]-x_[12]*x_[21];
+ f2 = x_[12]*x_[23]-x_[13]*x_[22];
+ f3 = x_[13]*x_[24]-x_[14]*x_[23];
+ f4 = x_[21]*x_[32]-x_[22]*x_[31];
+ f5 = x_[22]*x_[33]-x_[23]*x_[32];
+ f6 = x_[23]*x_[34]-x_[24]*x_[33];
+END;
diff --git a/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_regenCascade.input b/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_regenCascade.input
new file mode 100644
index 0000000..1b920fa
--- /dev/null
+++ b/test/data/Bertini_examples/Chap9WitnessGeneration/AdjacentMinors_regenCascade.input
@@ -0,0 +1,20 @@
+% Adjacent Minors: witness generation by regenerative cascade
+%
+CONFIG
+ TrackType:1;
+ WitnessGenType:2; % regenerative cascade (could omit, as this is the default)
+ WitnessSupersetOnly:1; % only compute a witness point superset
+END;
+INPUT
+ function f1,f2,f3,f4,f5,f6;
+ variable_group x_[11],x_[12],x_[13],x_[14],
+ x_[21],x_[22],x_[23],x_[24],
+ x_[31],x_[32],x_[33],x_[34];
+
+ f1 = x_[11]*x_[22]-x_[12]*x_[21];
+ f2 = x_[12]*x_[23]-x_[13]*x_[22];
+ f3 = x_[13]*x_[24]-x_[14]*x_[23];
+ f4 = x_[21]*x_[32]-x_[22]*x_[31];
+ f5 = x_[22]*x_[33]-x_[23]*x_[32];
+ f6 = x_[23]*x_[34]-x_[24]*x_[33];
+END;
diff --git a/test/data/Bertini_examples/README.md b/test/data/Bertini_examples/README.md
new file mode 100644
index 0000000..adf3a8c
--- /dev/null
+++ b/test/data/Bertini_examples/README.md
@@ -0,0 +1,4 @@
+# Bertini book examples
+
+The examples in this folder are all taken from *Numerically solving polynomial systems with Bertini*.
+They may be obtained [here](https://bertini.nd.edu/BertiniExamples/).
\ No newline at end of file
diff --git a/test/data/README.md b/test/data/README.md
new file mode 100644
index 0000000..696923f
--- /dev/null
+++ b/test/data/README.md
@@ -0,0 +1,4 @@
+# Examples
+
+Examples in this directory, except the `Bertini_examples` subdirectory and `zero_dim/parameter_homotopy`,
+may all be obtained from the [Bertini tarball](https://bertini.nd.edu/download.html).
\ No newline at end of file
diff --git a/test/data/zero_dim/parameter_homotopy/input b/test/data/zero_dim/parameter_homotopy/input
new file mode 100644
index 0000000..fdec76c
--- /dev/null
+++ b/test/data/zero_dim/parameter_homotopy/input
@@ -0,0 +1,10 @@
+CONFIG
+parameterhomotopy:1;
+randomseed:10191;
+END;
+INPUT
+variable_group x;
+parameter a0,a1,a2,a3,a4,a5,a6;
+function f;
+f = a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))));
+END;
diff --git a/test/test_input_file.py b/test/test_input_file.py
new file mode 100644
index 0000000..1805ea6
--- /dev/null
+++ b/test/test_input_file.py
@@ -0,0 +1,18 @@
+from collections import OrderedDict
+
+from bertini.io.input_file.input_section import BertiniInput
+
+
+def test_inputs_parameter_homotopy():
+ inputs = BertiniInput(variable_group=[["x"]],
+ parameter=OrderedDict((f"a{i}", None) for i in range(7)),
+ function=OrderedDict(f="a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))))"))
+ assert inputs.variable_group == [["x"]]
+ assert "a0" in inputs.parameter and inputs.parameter["a0"] is None
+ assert "a1" in inputs.parameter and inputs.parameter["a1"] is None
+ assert "a2" in inputs.parameter and inputs.parameter["a2"] is None
+ assert "a3" in inputs.parameter and inputs.parameter["a3"] is None
+ assert "a4" in inputs.parameter and inputs.parameter["a4"] is None
+ assert "a5" in inputs.parameter and inputs.parameter["a5"] is None
+ assert "a6" in inputs.parameter and inputs.parameter["a6"] is None
+ assert inputs.function["f"] == "a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))))"
diff --git a/test/test_io.py b/test/test_io.py
new file mode 100644
index 0000000..011951f
--- /dev/null
+++ b/test/test_io.py
@@ -0,0 +1,80 @@
+from conftest import op, ZERO_DIM_BASE, POS_DIM_BASE
+
+from bertini.io.utils import read_input_file
+from bertini.io.input_file.input_section import BertiniInput
+from bertini.io.input_file.config_section import BertiniConfig
+
+
+def is_empty(x):
+ return len(x) == 0
+
+
+def test_read_input1():
+ config, inputs, misclines = read_input_file(op.join(POS_DIM_BASE, "sampling", "input"))
+
+ assert isinstance(config, BertiniConfig)
+ assert config.tracktype == 2
+ assert config.mptype == 2
+ assert config.precision == 96
+ assert config.coeffbound == 1000
+ assert config.degreebound == 5
+ assert config.ampmaxprec == 1024
+ assert config.parameterhomotopy == 0
+ assert config.randomseed == 0
+
+ assert isinstance(inputs, BertiniInput)
+ assert is_empty(inputs.constant)
+ assert is_empty(inputs.variable)
+ assert is_empty(inputs.hom_variable_group)
+ assert is_empty(inputs.subfunction)
+ assert is_empty(inputs.parameter)
+ assert is_empty(inputs.random)
+ assert is_empty(inputs.random_real)
+ assert is_empty(inputs.pathvariable)
+ assert inputs.ndims == 3
+ assert len(inputs.variable_group) == 1
+ assert inputs.variable_group[0] == ["x", "y", "z"]
+ assert len(inputs.function) == 3
+ assert inputs.function["f1"] == "(y-x^2)*(x^2+y^2+z^2-1)*(x-0.5)"
+ assert inputs.function["f2"] == "(z-x^3)*(x^2+y^2+z^2-1)*(y-0.5)"
+ assert inputs.function["f3"] == "(y-x^2)*(z-x^3)*(x^2+y^2+z^2-1)*(z-0.5)"
+
+ assert isinstance(misclines, list) and len(misclines) == 0
+
+
+def test_read_input2():
+ config, inputs, misclines = read_input_file(op.join(ZERO_DIM_BASE, "parameter_homotopy", "input"))
+
+ assert isinstance(config, BertiniConfig)
+ assert config.tracktype == 0
+ assert config.mptype == 2
+ assert config.precision == 96
+ assert config.coeffbound == 1000
+ assert config.degreebound == 5
+ assert config.ampmaxprec == 1024
+ assert config.parameterhomotopy == 1
+ assert config.randomseed == 10191
+
+ assert isinstance(inputs, BertiniInput)
+ assert is_empty(inputs.constant)
+ assert is_empty(inputs.variable)
+ assert is_empty(inputs.hom_variable_group)
+ assert is_empty(inputs.subfunction)
+ assert len(inputs.parameter) == 7
+ assert inputs.parameter["a0"] is None
+ assert inputs.parameter["a1"] is None
+ assert inputs.parameter["a2"] is None
+ assert inputs.parameter["a3"] is None
+ assert inputs.parameter["a4"] is None
+ assert inputs.parameter["a5"] is None
+ assert inputs.parameter["a6"] is None
+ assert is_empty(inputs.random)
+ assert is_empty(inputs.random_real)
+ assert is_empty(inputs.pathvariable)
+ assert inputs.ndims == 1
+ assert len(inputs.variable_group) == 1
+ assert inputs.variable_group[0] == ["x"]
+ assert len(inputs.function) == 1
+ assert inputs.function["f"] == "a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))))"
+
+ assert isinstance(misclines, list) and len(misclines) == 0
diff --git a/test/test_parameter_homotopy.py b/test/test_parameter_homotopy.py
index 7f7b440..bffc408 100644
--- a/test/test_parameter_homotopy.py
+++ b/test/test_parameter_homotopy.py
@@ -1,11 +1,46 @@
-# -*- coding: utf-8 -*-
+from conftest import op, ZERO_DIM_BASE
-from context import op, TESTBASE
+from collections import OrderedDict
-from naglib.bertini.io import read_witness_data
+import numpy as np
-#class TestReadWitnessData:
-# def setup(self):
-#
+from bertini.io.utils import write_input_file
+from bertini.run import BertiniRun
+from bertini.io.input_file.input_section import BertiniInput
+from bertini.io.input_file.config_section import BertiniConfig
-wd = read_witness_data(op.join(TESTBASE, "pos_dim", "basic_pos_dim", "witness_data"))
\ No newline at end of file
+
+class TestParameterHomotopy:
+ def setup_method(self):
+ self.working_dir = op.join(ZERO_DIM_BASE, "parameter_homotopy")
+ self.inputs = BertiniInput(variable_group=[["x"]],
+ parameter=OrderedDict((f"a{i}", None) for i in range(7)),
+ function=OrderedDict(f="a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))))"))
+
+ self.config = BertiniConfig(parameterhomotopy=1, randomseed=10191)
+
+ print("initial run")
+ brun = BertiniRun(self.config, self.inputs, mpi_path=None)
+ self.ab_initio_result = brun.run(dirname=self.working_dir)
+
+ def test_ab_initio_result(self):
+ finite_solutions = np.array([[0.78101599+0.18185757j, 0.33253178+1.4856318j,
+ -0.71413828+1.01669647j, -0.53917013-0.04838107j,
+ -0.65402653-0.7627159j , 0.43428293-0.98042348j]])
+ assert np.linalg.norm(finite_solutions - self.ab_initio_result.finite_solutions) < 1e-8
+
+ def test_parameter_homotopy2(self):
+ start_parameters = self.ab_initio_result.start_parameters
+ final_parameters = np.array([1.1, 2.4, 0.8, 3.6, -0.52, -1.8, 4.4], dtype=np.complex)
+ self.config.parameterhomotopy = 2
+
+ brun = BertiniRun(self.config, self.inputs, start=self.ab_initio_result.nonsingular_solutions,
+ start_parameters=start_parameters, final_parameters=final_parameters, mpi_path=None)
+
+ self.final_result = brun.run(dirname=self.working_dir)
+ assert isinstance(self.final_result.config, BertiniConfig)
+ assert isinstance(self.final_result.inputs, BertiniInput)
+
+ def teardown_method(self):
+ self.config.parameterhomotopy = 1
+ write_input_file(self.config, self.inputs, op.join(self.working_dir, "input"))
\ No newline at end of file
diff --git a/test/test_write_input.py b/test/test_write_input.py
deleted file mode 100644
index 4a4a9c3..0000000
--- a/test/test_write_input.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from context import op, TESTBASE
-
-from collections import deque, OrderedDict
-
-class TestParameterHomotopy1:
- def setup(self):
- self.inputs = dict(variable_group=deque(["x"]),
- variable=deque(),
- hom_variable_group=deque(),
- pathvariable=deque(),
- random=deque(),
- random_real=deque(),
- constant=OrderedDict(),
- function=OrderedDict(f="a0+x*(a1+x*(a2+x*(a3+x*(a4+x*(a5+x*a6)))))"),
- parameter=OrderedDict((f"a{i}", None) for i in range(7)),
- subfunction=OrderedDict())
- self.config = {"ParameterHomotopy": 1}
- self.input_file = op.join(TESTBASE, "input")
diff --git a/tox.ini b/tox.ini
index 37a6fe8..97ea8d9 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,8 +1,6 @@
[tox]
envlist = py36,py37,doc,dist
-[pytest]
-addopts=-s --cov-conf test/.coveragerc --cov=naglib test/ --doctest-modules --open-files
[testenv:py36]
deps =