Constrained tuning: Difference between revisions

m Display style. Mark todo
Computation: I'm no longer using the SQP routine
Line 35: Line 35:


== Computation ==
== Computation ==
As a standard optimization problem, numerous algorithms exist to solve it, such as {{w|sequential quadratic programming}}, to name one. [[Flora Canou]]'s [https://github.com/FloraCanou/temperament_evaluator/blob/v0.26.4/te_optimizer_legacy.py tuning optimizer] is such an implementation in [https://www.python.org Python]. Note: it uses [https://scipy.org/ Scipy].  
As a standard optimization problem, numerous algorithms exist to solve it, such as {{w|sequential quadratic programming}}, to name one. [[Flora Canou]]'s [https://github.com/FloraCanou/temperament_evaluator/blob/master/te_optimizer_legacy.py tuning optimizer] solves constrained tuning problems in [https://www.python.org Python], using [https://scipy.org/ Scipy].  


{{Databox| Code |
{{Databox| Code |
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
# © 2020-2023 Flora Canou | Version 0.27.2
# © 2020-2025 Flora Canou
# This work is licensed under the GNU General Public License version 3.
# This work is licensed under the GNU General Public License version 3.
# Version 0.28.0


import warnings
import warnings
import numpy as np
import numpy as np
from scipy import optimize, linalg
from scipy import optimize, linalg
np.set_printoptions (suppress = True, linewidth = 256, precision = 4)
np.set_printoptions (suppress = True, linewidth = 256, precision = 3)


PRIME_LIST = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89]
PRIME_LIST = [
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,  
    41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
]


class SCALAR:
class SCALAR:
Line 115: Line 119:
         print ("Euclidean tuning without constraints, solved using lstsq. ")
         print ("Euclidean tuning without constraints, solved using lstsq. ")
     else:
     else:
         gen0 = [SCALAR.CENT]*breeds.shape[0] #initial guess
         gen0 = just_tuning_map[:breeds.shape[0]] #initial guess
         cons = () if cons_monzo_list is None else {
         cons = optimize.LinearConstraint ((breeds @ cons_monzo_list).T,
             'type': 'eq',  
             lb = (just_tuning_map @ cons_monzo_list).T,  
             'fun': lambda gen: (gen @ breeds - just_tuning_map) @ cons_monzo_list
             ub = (just_tuning_map @ cons_monzo_list).T
         }
         )
         res = optimize.minimize (lambda gen: linalg.norm (gen @ breeds_x - just_tuning_map_x, ord = norm.order), gen0,  
         res = optimize.minimize (lambda gen: linalg.norm (gen @ breeds_x - just_tuning_map_x, ord = norm.order), gen0,  
             method = "SLSQP", options = {'ftol': 1e-9}, constraints = cons)
             method = "COBYQA", constraints = cons)
         print (res.message)
         print (res.message)
         if res.success:
         if res.success:
Line 161: Line 165:


<pre>
<pre>
Optimization terminated successfully.
The lower bound for the trust-region radius has been reached
Generators: [1200.     1896.9521] (¢)
Generators: [1200.   1896.952] (¢)
Tuning map: [1200.     1896.9521 2787.8085 3369.5214] (¢)
Tuning map: [1200.   1896.952 2787.809 3369.521] (¢)
Error map: [ 0.     -5.0029 1.4948 0.6955] (¢)
Error map: [ 0.   -5.003 1.495 0.695] (¢)
</pre>
</pre>