0

This is a pretty general scenario, but to give some context, let's say I am using cvxpy to do some constrained optimization. Now say I want to supply the objective function at runtime, such as func below:

import cvxpy as cp

class foo:
  def __init__(self,n,q,s):
    self.n,self.q,self.s=n,q,s
    self.K = len(n)
    self.x = cp.Variable(self.K)
    self.func = cp.sum(sum(self.n[j]*sum(self.n[i]*self.x[j] for i in range(self.K)) for j in range(self.K))

Of course, the function in the example is a contrived one, just to give you an example of what sort of string expression I am willing to supply as a command-line parameter, just to avoid hardcoding stuff / changing the source code all the time. How I can override this func member's value with a new one, at runtime? I read about exec, but I am not sure if that helps. In short, I am willing to do something like python my_awesom_prog.py "self.n[i]*self.n[j] for i in range(self.K) for range(self.K)" and I would like the program behave as if this (horrible) string has been there as the definition of func in the first place. EDIT: more to the point, I would like to have a method like this:

def reset_objective(mystring):
   self.func = interpret_as_cvxpy_entity(mystring)

Now, how to get hold of that interpret_as_cvxpy_entity API?

Ilonpilaaja
  • 1,169
  • 2
  • 15
  • 26

1 Answers1

0

You can use input() and eval(). So, something like:

import cvxpy as cp

class foo:
  def __init__(self,n,q,s):
    self.n,self.q,self.s=n,q,s
    self.K = len(n)
    self.x = cp.Variable(self.K)
    self.func = eval(input())

Then you can run your script as python my_awesom_prog.py and "self.n[i]*self.n[j] for i in range(self.K) for range(self.K)" as the input.

I should warn you of the danger of eval(input()). For instance, you could input code within the eval function that deletes every file on your computer. For more info on why you shouldn't do this, I refer you to the following article:

https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html

James Carter
  • 803
  • 2
  • 10
  • 18