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 =