Some background before the actual code:

My team needs to develop an optimization library for a specific problem. In order to optimize (pun intended) the projects life-cycle I am trying to write some interfaces that my peers (who are data scientist with small interest and experience in programming) can easily implement. For this reason the only requirement I am looking to fulfill is the readability and extensibility of the code, as it will never go into production.

The optimizer interface:

class ProtonOptimizer(object):
An abstract class defining a common interface to be used by all our future models.
Make sure you comply to the API meaning that your concrete class should:
1) Be constructed by providing the BED values as a 2D np array and the capacity
2) It should return its result by implementing the get_optimum() method
  def __init__(self, BED, capacity = 100, model_name = 'abstract_therapy'):
    raise NotImplementedError("You cannot construct an abstract class")

  def get_optimum():
    """Returns a dictionary (int -> int) from patient ID to fractions"""
    return {}

  def pretty_print():
    """Override to print your models output in a meaningful way for debugging purposes"""
    print("The optimum is " + str(self.get_optimum()))

The sample implementation I provided:

class LPOptimizer(ProtonOptimizer):
"""Concrete implementation of the ProtonOptimizer interface"""
  def __init__(self, BED, capacity = 100, model_name = 'proton_therapy'):
    self._BED = BED
    num_patients, max_fractions_per_patient = BED.shape
    self.patients = [i for i in range(num_patients)]
    self.fractions = [j for j in range(max_fractions_per_patient)]
    self.m = Model(model_name)

    # Set binary decision variables
    self.x = self.m.addVars(num_patients, max_fractions_per_patient, vtype = GRB.BINARY) 

    # We can only perform so many proton therapies per week
        quicksum(self.x[i,j] * self.fractions[j] for j in self.fractions) 
        for i in self.patients) <= capacity)

    self.optimum = {}

  def _solve(self, debug = False):
    # Set objective
        self.x[i,j] * self._BED[i,j] for i in self.patients for j in self.fractions),

    self.m.setParam('OutputFlag', debug)
    if self.m.status == GRB.Status.OPTIMAL:
        solution = self.m.getAttr("x", self.x)
        for i in self.patients:
            for j in self.fractions:
                if(solution[i,j] == 1):
                    self.optimum[i] = j
        print("Infeasible model")

  def pretty_print(self):
    solution = self.get_optimum()
    for patient, fractions in solution.items():
        print(("Patient " + str(patient) + " should receive " + str(fractions) + " fractions"))

  def get_optimum(self):
    if not self.optimum:
    return self.optimum

The actual question: The goal here is to enable my peers to write other implementations of the ProtonOptimizer but be able to test all of them uniformly later (this is why i demand that every implementation has a get_optimum() function that returns a dict). Is this design actually helping them achieve it? How can I make it as easy for them as possible to contribute?


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.