Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

Commit 05c387d2 authored by Jose Ignacio Requeno Jarabo's avatar Jose Ignacio Requeno Jarabo
Browse files

Merge branch 'OracleMatlab' into 'master'

Oracle matlab

See merge request requenoj/multidimensional_search!1
parents a6ff05e4 5b99cdc6
Pipeline #31139 canceled with stages
in 5 minutes and 53 seconds
......@@ -21,7 +21,7 @@ build_test:
## Installing
- ./install.sh
## Testing
- pytest --ignore=Tests/test_Search.py
- pytest --ignore=Tests/test_Search.py --ignore=Tests/test_Oracle_OracleMatlab.py
- cd Tests
- pytest test_Search.py::SearchOracleFunctionTestCase
......@@ -63,4 +63,8 @@ test:
- cd dist/
- pip install *.whl --user
- cd ../Tests
- ./coverage_all.sh
\ No newline at end of file
- ./coverage_all.sh
artifacts:
when: on_success
paths:
- coverage/report-python/*
\ No newline at end of file
# -*- coding: utf-8 -*-
# Copyright (c) 2018 J.I. Requeno et al
#
# This file is part of the ParetoLib software tool and governed by the
# 'GNU License v3'. Please see the LICENSE file that should have been
# included as part of this software.
"""OracleMatlab.
This module instantiate the abstract interface Oracle.
The OracleMatlab interacts with parametrized Matlab models.
"""
import pickle
import io
import os
import sys
import matlab.engine
import ParetoLib.Oracle as RootOracle
from ParetoLib.Oracle.Oracle import Oracle
from ParetoLib._py3k import get_stdout_matlab, get_stderr_matlab
class OracleMatlab(Oracle):
def __init__(self, matlab_model_file=''):
# type: (OracleMatlab, str) -> None
"""
An OracleMatlab is a set of Conditions.
"""
# super(OracleMatlab, self).__init__()
Oracle.__init__(self)
# Initialize the Matlab Engine
self.out = None
self.err = None
self.eng = None
# Matlab function 'f' not loaded yet.
# Dimension of the space unknown
self.f = None
self.d = None
self.matlab_model_file = matlab_model_file
def _load_matlab_engine(self):
# type: (OracleMatlab) -> None
assert self.matlab_model_file != ''
# Lazy initialization of the Matlab engine
RootOracle.logger.debug('Initializing Matlab engine')
self.out = get_stdout_matlab()
self.err = get_stderr_matlab()
self.eng = matlab.engine.start_matlab()
RootOracle.logger.debug('Matlab engine {0}'.format(self.eng))
def _load_function(self):
# type: (OracleMatlab) -> None
assert self.matlab_model_file != '', 'Matlab function not defined'
# assert self.eng is not None, 'Matlab engine not started'
RootOracle.logger.debug('Loading Matlab function')
if self.eng is None:
self._load_matlab_engine()
# Include the path of the Matlab model in the Matlab workspace
self.eng.addpath(os.path.dirname(self.matlab_model_file))
# Extract the name of the Matlab function.
# If the Matlab filename is 'matlab_model.m' then:
#
# self.eng.matlab_model(*args, **kwargs)
#
# will invoke the code
# matlab_model_file = '/path/to/matlab_model.m'
# filename, file_extension = ('/path/to/matlab_model', '.m')
filename, file_extension = os.path.splitext(self.matlab_model_file)
# func_name = 'matlab_model'
func_name = os.path.basename(filename)
# Extract from Matlab the function 'f' that will be used as Oracle
# self.f = self.eng.__getattr__('matlab_model')
self.f = self.eng.__getattr__(func_name)
# Dimension, i.e., equivalent to the number of in arguments of the function 'f'
self.d = int(self.eng.nargin(func_name))
RootOracle.logger.debug('Function {0} with {1} parameters'.format(func_name, self.d))
RootOracle.logger.debug('Matlab function {0}'.format(self.f))
def __setattr__(self, name, value):
# type: (OracleMatlab, str, None) -> None
"""
Assignation of a value to a class attribute.
Args:
self (OracleMatlab): The OracleMatlab.
name (str): The attribute.
value (None): The value
Returns:
None: self.name = value.
Example:
>>> matlab_model_file = 'test1.m'
>>> ora = OracleMatlab()
>>> ora.matlab_model_file = matlab_model_file
"""
object.__setattr__(self, name, value)
str_matlab_file = 'matlab_model_file'
if (name == str_matlab_file) and (value.strip() != ''):
self.f = None
self.d = None
def __repr__(self):
# type: (OracleMatlab) -> str
"""
Printer.
"""
return self.matlab_model_file
def __str__(self):
# type: (OracleMatlab) -> str
"""
Printer.
"""
return self.matlab_model_file
def __eq__(self, other):
# type: (OracleMatlab, OracleMatlab) -> bool
"""
self == other
"""
return self.matlab_model_file == other.matlab_model_file
def __ne__(self, other):
# type: (OracleMatlab, OracleMatlab) -> bool
"""
self != other
"""
return not self.__eq__(other)
def __hash__(self):
# type: (OracleMatlab) -> int
"""
Identity function (via hashing).
"""
return hash(tuple(self.matlab_model_file))
def __del__(self):
# type: (OracleMatlab) -> None
"""
Removes 'self' from the namespace.
"""
if self.eng is not None:
self.eng.quit()
def __copy__(self):
# type: (OracleMatlab) -> OracleMatlab
"""
other = copy.copy(self)
"""
RootOracle.logger.debug('__copy__: {0}'.format(self))
return OracleMatlab(matlab_model_file=self.matlab_model_file)
def __deepcopy__(self, memo):
# type: (OracleMatlab, dict) -> OracleMatlab
"""
other = copy.deepcopy(self)
"""
# deepcopy function is required for creating multiple instances of the Oracle in ParSearch.
# deepcopy cannot handle neither matlab.engine nor matlab.func
RootOracle.logger.debug('__deeopcopy__: {0}'.format(self))
return OracleMatlab(matlab_model_file=self.matlab_model_file)
def __getattr__(self, name):
# type: (OracleMatlab, str) -> _
"""
Returns:
self.name (object attribute)
"""
elem = object.__getattribute__(self, name)
if (elem is None) and (name in ['f', 'd']):
self._load_function()
elem = object.__getattribute__(self, name)
# elif (elem is None) and (name == 'eng'):
# self._load_matlab_engine()
# elem = object.__getattribute__(self, name)
RootOracle.logger.debug('__getattr__: {0}, {1}'.format(name, elem))
return elem
def __getattribute__(self, name):
# type: (OracleMatlab, str) -> _
"""
Returns:
self.name (object attribute)
"""
elem = object.__getattribute__(self, name)
RootOracle.logger.debug('__getattribute__: {0}, {1}'.format(name, elem))
if elem is None:
raise AttributeError
return elem
def dim(self):
# type: (OracleMatlab) -> int
"""
See Oracle.dim().
"""
return self.d
def get_var_names(self):
# type: (OracleMatlab) -> list
"""
See Oracle.get_var_names().
"""
return ['p'+str(i) for i in range(self.d)]
def __contains__(self, point):
# type: (OracleMatlab, tuple) -> bool
"""
Synonym of self.member(point).
A point belongs to the Oracle if it satisfies all the conditions.
"""
return self.member(point) is True
def member(self, point):
# type: (OracleMatlab, tuple) -> bool
"""
See Oracle.member().
"""
return self.f(*point, stdout=self.out, stderr=self.err)
def membership(self):
# type: (OracleMatlab) -> callable
"""
See Oracle.membership().
"""
return lambda point: self.member(point)
# Read/Write file functions
def from_file_binary(self, finput=None):
# type: (OracleMatlab, io.BinaryIO) -> None
"""
See Oracle.from_file_binary().
"""
assert (finput is not None), 'File object should not be null'
try:
current_path = os.path.dirname(os.path.abspath(finput.name))
path = pickle.load(finput)
matlab_model_file = os.path.join(current_path, path) if not os.path.isabs(path) else path
if not os.path.isfile(matlab_model_file):
RootOracle.logger.info('File {0} does not exists or it is not a file'.format(matlab_model_file))
self.matlab_model_file = matlab_model_file
except EOFError:
RootOracle.logger.error('Unexpected error when loading {0}: {1}'.format(finput, sys.exc_info()[0]))
def from_file_text(self, finput=None):
# type: (OracleMatlab, io.BinaryIO) -> None
"""
See Oracle.from_file_text().
"""
assert (finput is not None), 'File object should not be null'
try:
# The file contains the path to the Matlab file containing the parametrized model.
#
# os.path.join creates absolute path from relative path "./something.txt"
# os.path.realpath uniforms path "2D/./test.m" by "2D/test.m"
#
current_path = os.path.dirname(os.path.abspath(finput.name))
path = finput.readline().strip(' \n\t')
matlab_model_file = os.path.join(current_path, path) if not os.path.isabs(path) else path
matlab_model_file = os.path.realpath(matlab_model_file)
if not os.path.isfile(matlab_model_file):
RootOracle.logger.info('File {0} does not exists or it is not a file'.format(matlab_model_file))
self.matlab_model_file = matlab_model_file
except EOFError:
RootOracle.logger.error('Unexpected error when loading {0}: {1}'.format(finput, sys.exc_info()[0]))
def to_file_binary(self, foutput=None):
# type: (OracleMatlab, io.BinaryIO) -> None
"""
See Oracle.to_file_binary().
"""
assert (foutput is not None), 'File object should not be null'
pickle.dump(os.path.abspath(self.matlab_model_file), foutput, pickle.HIGHEST_PROTOCOL)
def to_file_text(self, foutput=None):
# type: (OracleMatlab, io.BinaryIO) -> None
"""
See Oracle.to_file_text().
"""
assert (foutput is not None), 'File object should not be null'
foutput.write(os.path.abspath(self.matlab_model_file) + '\n')
......@@ -197,7 +197,7 @@ class OracleSTLe(Oracle):
"""
elem = object.__getattribute__(self, name)
if elem is None:
RootOracle.logger.debug('Initializing OracleSTLe')
RootOracle.logger.debug('Initializing Oracle')
self._lazy_init()
elem = object.__getattribute__(self, name)
RootOracle.logger.debug('Initialized Oracle')
......
......@@ -14,7 +14,7 @@ of the module.
import logging
__name__ = 'Oracle'
__all__ = ['NDTree', 'Oracle', 'OracleFunction', 'OraclePoint', 'OracleSTL', 'OracleSTLe']
__all__ = ['NDTree', 'Oracle', 'OracleFunction', 'OraclePoint', 'OracleSTL', 'OracleSTLe', 'OracleMatlab']
# Logging configuration
# logging.basicConfig(format='%(message)s', level=logging.INFO)
......
......@@ -209,8 +209,9 @@ def multidim_search_deep_first_opt_3(xspace,
# 'f = oracle.membership()' is not thread safe!
# Create a copy of 'oracle' for each concurrent process
# dict_man = {proc: copy.deepcopy(oracle) for proc in mp.active_children()}
# dict_man = {proc.name: copy.deepcopy(oracle) for proc in mp.active_children()}
for proc in mp.active_children():
RootSearch.logger.debug('cloning: {0}'.format(oracle))
dict_man[proc.name] = copy.deepcopy(oracle)
RootSearch.logger.debug('xspace: {0}'.format(xspace))
......@@ -457,8 +458,9 @@ def multidim_search_deep_first_opt_2(xspace,
# 'f = oracle.membership()' is not thread safe!
# Create a copy of 'oracle' for each concurrent process
# dict_man = {proc: copy.deepcopy(oracle) for proc in mp.active_children()}
# dict_man = {proc.name: copy.deepcopy(oracle) for proc in mp.active_children()}
for proc in mp.active_children():
RootSearch.logger.debug('cloning: {0}'.format(oracle))
dict_man[proc.name] = copy.deepcopy(oracle)
RootSearch.logger.debug('xspace: {0}'.format(xspace))
......@@ -678,8 +680,9 @@ def multidim_search_deep_first_opt_1(xspace,
# 'f = oracle.membership()' is not thread safe!
# Create a copy of 'oracle' for each concurrent process
# dict_man = {proc: copy.deepcopy(oracle) for proc in mp.active_children()}
# dict_man = {proc.name: copy.deepcopy(oracle) for proc in mp.active_children()}
for proc in mp.active_children():
RootSearch.logger.debug('cloning: {0}'.format(oracle))
dict_man[proc.name] = copy.deepcopy(oracle)
RootSearch.logger.debug('xspace: {0}'.format(xspace))
......@@ -896,8 +899,9 @@ def multidim_search_deep_first_opt_inf(xspace,
# 'f = oracle.membership()' is not thread safe!
# Create a copy of 'oracle' for each concurrent process
# dict_man = {proc: copy.deepcopy(oracle) for proc in mp.active_children()}
# dict_man = {proc.name: copy.deepcopy(oracle) for proc in mp.active_children()}
for proc in mp.active_children():
RootSearch.logger.debug('cloning: {0}'.format(oracle))
dict_man[proc.name] = copy.deepcopy(oracle)
RootSearch.logger.debug('xspace: {0}'.format(xspace))
......@@ -1083,8 +1087,9 @@ def multidim_search_deep_first_opt_0(xspace,
# 'f = oracle.membership()' is not thread safe!
# Create a copy of 'oracle' for each concurrent process
# dict_man = {proc: copy.deepcopy(oracle) for proc in mp.active_children()}
# dict_man = {proc.name: copy.deepcopy(oracle) for proc in mp.active_children()}
for proc in mp.active_children():
RootSearch.logger.debug('cloning: {0}'.format(oracle))
dict_man[proc.name] = copy.deepcopy(oracle)
RootSearch.logger.debug('xspace: {0}'.format(xspace))
......
......@@ -47,6 +47,15 @@ if (sys.version_info[0] >= 3):
return dictionary.items()
def get_stdout_matlab():
"""Return a Standard output stream for Matlab."""
return io.StringIO()
def get_stderr_matlab():
"""Return a Standard error stream for Matlab."""
return io.StringIO()
# On Python 3 urllib, urllib2, and urlparse were merged
from urllib.request import urlopen, Request, urlretrieve, urlparse
from urllib.parse import urlencode, quote
......@@ -63,6 +72,7 @@ else: # sys.version_info[0] < 3
from future_builtins import zip, map, filter
from __builtin__ import xrange as range
from __builtin__ import raw_input as input
import StringIO
def red(function, sequence):
"""Call 'reduce', which applies 'function' over all the elements of the sequence"""
......@@ -89,6 +99,13 @@ else: # sys.version_info[0] < 3
"""Return a view of the items of 'dictionary'."""
return dictionary.viewitems()
def get_stdout_matlab():
"""Return a Standard output stream for Matlab."""
return StringIO.StringIO()
def get_stderr_matlab():
"""Return a Standard error stream for Matlab."""
return StringIO.StringIO()
# Under urllib.request on Python 3:
from urllib2 import urlopen, Request
......@@ -104,14 +121,14 @@ else: # sys.version_info[0] < 3
# On Python 2 this will be a (bytes) string based handle.
# Note this doesn't work as it is unicode based:
# from io import StringIO
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
try:
input = raw_input
except NameError:
pass
# try:
# from cStringIO import StringIO
# except ImportError:
# from StringIO import StringIO
# try:
# input = raw_input
# except NameError:
# pass
# There is no TemporaryDirectory class in the temp library
from TemporaryDirectory import TemporaryDirectory
......
function t1 = test1(x, y)
t1 = (x > 0) && (y > 1-x)
end
./test1.m
\ No newline at end of file
function t2 = test2(x, y)
t2 = (x > 0) && (y > 1-x**2)
end
function t3 = test3(x, y)
t3 = (x > 0) && (y >= 1/x)
end
function t4 = test4(x, y)
t4 = (x**2 + y**2 > 0.5**2)
end
function t5 = test5(x, y)
t5 = (x + y > 1)
end
\ No newline at end of file
function t1 = test1(x, y, z)
t1 = (x > 0) && (y > 1-x) && (z > 0)
end
./test1.m
\ No newline at end of file
function t2 = test2(x, y, z)
t2 = (x > 0) && (y > 1-x**2) && (z > 0)
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment