Source code for desdeo.utils.misc

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Copyright (c) 2016  Vesa Ojalehto
"""Miscellaneous utilities
"""

import datetime
import sys
from typing import List, Tuple

import numpy as np
from sklearn.cluster.k_means_ import KMeans
from sklearn.metrics.pairwise import pairwise_distances_argmin_min

from desdeo.core.ResultFactory import IterationPointFactory


class Tee(object):
    """ Appends  stdout to a logfile.

    Note that a Tee instance will replace stdout until it has been deleted.
    """

    def __init__(self, logfile, date_format="%Y-%m-%d %H:%M"):
        self.terminal = sys.stdout
        sys.stdout = self
        self.date_format = date_format
        self.log = open(logfile, "a")
        self.__buffer = ""

    def write(self, message):

        self.terminal.write(message)
        self.__buffer += message
        if "\n" in self.__buffer:
            self.log.write(
                f"{datetime.datetime.now():{self.date_format}} {self.__buffer}"
            )
            self.__buffer = ""

    def __del__(self):
        sys.stdout = self.terminal
        self.log.close()

    def flush(self):
        self.log.flush()


def _centroids(n_clusters: int, points: List[List[float]]) -> List[List[float]]:
    """ Return n_clusters centroids of points
    """

    k_means = KMeans(n_clusters=n_clusters)
    k_means.fit(points)

    closest, _ = pairwise_distances_argmin_min(k_means.cluster_centers_, points)

    return list(map(list, np.array(points)[closest.tolist()]))


[docs]def random_weights(nobj: int, nweight: int) -> List[List[float]]: """ Generatate nw random weight vectors for nof objectives as per Tchebycheff method [SteCho83]_ .. [SteCho83] Steuer, R. E. & Choo, E.-U. An interactive weighted Tchebycheff procedure for multiple objective programming, Mathematical programming, Springer, 1983, 26, 326-344 Parameters ---------- nobj: Number of objective functions nweight: Number of weights vectors to be generated Returns ------- List[List[float] nobj x nweight matrix of weight vectors """ # Initial wector space as per # Miettinen, K. Nonlinear Multiobjective Optimization # Kluwer Academic Publishers, 1999 wspace = 50 * nobj while wspace < nweight: wspace *= 2 weights = np.random.rand(wspace, nobj) return _centroids(nobj, weights)
[docs]def new_points( factory: IterationPointFactory, solution, weights: List[List[float]] = None ) -> List[Tuple[np.ndarray, List[float]]]: """Generate approximate set of points Generate set of Pareto optimal solutions projecting from the Pareto optimal solution using weights to determine the direction. Parameters ---------- factory: IterationPointFactory with suitable optimization problem solution: Current solution from which new solutions are projected weights: Direction of the projection, if not given generate with :func:random_weights """ from desdeo.preference.direct import DirectSpecification points = [] nof = factory.optimization_method.optimization_problem.problem.nof_objectives() if not weights: weights = random_weights(nof, 50 * nof) for pref in map( lambda w: DirectSpecification(factory.optimization_method, np.array(w)), weights ): points.append(factory.result(pref, solution)) return points
[docs]def as_minimized(values: List[float], maximized: List[bool]) -> List[float]: """ Return vector values as minimized """ return [v * -1. if m else v for v, m in zip(values, maximized)]