Skip to content

Commit

Permalink
Merge pull request #11 from yvanoers/enqueue-items
Browse files Browse the repository at this point in the history
Enqueue work items instead of a list of them
  • Loading branch information
wouterbles authored Aug 9, 2023
2 parents 7400094 + 976d6e8 commit 2bc2e0a
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 98 deletions.
4 changes: 3 additions & 1 deletion pyaugmecon/queue_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,6 @@ def split_work(self):

for i, block in enumerate(blocks):
items = [tuple(item) for sublist in block.tolist() for item in sublist] # Flatten the sub-blocks
self.job_qs[i].put(items) # Put the flattened items in the job queue for the process
# Put the flattened items in the job queue for the process
for t in items:
self.job_qs[i].put(t)
193 changes: 96 additions & 97 deletions pyaugmecon/solver_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,107 +58,106 @@ def run(self):

# Run indefinitely until there's no more work
while True:
# Get work from queue for this process number
work = self.queues.get_work(self.p_num)
# Get job from queue for this process number
c = self.queues.get_work(self.p_num)

# If no more work, break the loop
if not work:
# If no more jobs, break the loop
if not c:
break

# Process each job in the work list
for c in work:
log = f"Process: {self.p_num}, index: {c}, " # Initialize logging string
cp_end = self.opts.gp - 1 # Set the end index for this job
self.model.progress.increment() # Increment progress counter for this model

# Define helper functions to handle jump, bypass, and early exit scenarios
def do_jump(i, jump):
return min(jump, abs(cp_end - i))

def bypass_range(i):
if i == 0:
return range(c[i], c[i] + 1)
else:
return range(c[i], c[i] + b[i] + 1)

def early_exit_range(i):
if i == 0:
return range(c[i], c[i] + 1)
else:
return range(c[i], cp_end)

# Check if flag is enabled and if the current job has a flag set
if self.opts.flag and self.flag.get(c) != 0 and jump == 0:
# If jump is not set and there's a flag for this job, set jump
jump = do_jump(c[0] - 1, self.flag.get(c))

# If jump is set, skip to the next iteration of the loop
if jump > 0:
jump = jump - 1
continue

# Log model progress for each objective
for o in self.model.iter_obj2:
log += f"e{o + 1}: {self.model.e[o, c[o]]}, "
self.model.model.e[o + 2] = self.model.e[o, c[o]]

# Activate objective 0 and solve the model
self.model.obj_activate(0)
self.model.solve()
self.model.models_solved.increment()

# Check if early exit is enabled and if the model is infeasible
if self.opts.early_exit and self.model.is_infeasible():
# If so, increment infeasibilities counter
self.model.infeasibilities.increment()

# Set flag if flag is enabled
if self.opts.flag:
self.flag.set(early_exit_range, self.opts.gp, self.model.iter_obj2)

jump = do_jump(c[0], self.opts.gp) # Set jump
log += "infeasible" # Log infeasibility

# Log progress if process logging is enabled
if self.opts.process_logging:
self.logger.info(log)

continue # Skip to next iteration of loop

# Calculate slack values and set jump if bypass is enabled
elif self.opts.bypass and self.model.is_optimal():
b = []
for i in self.model.iter_obj2:
step = self.model.obj_range[i] / (self.opts.gp - 1)
slack = round(self.model.slack_val(i + 1))
b.append(int(slack / step))

# Log jump and set flag if enabled
log += f"jump: {b[0]}, "
if self.opts.flag:
self.flag.set(bypass_range, b[0] + 1, self.model.iter_obj2)
jump = do_jump(c[0], b[0])

# If model is optimal, calculate and log solutions
sols = []
if self.model.is_optimal():
sols.append(
self.model.obj_val(0)
- self.opts.eps
* sum(
10 ** (-1 * (o)) * self.model.slack_val(o + 1) / self.model.obj_range[o]
for o in self.model.iter_obj2
)
# Process the job
log = f"Process: {self.p_num}, index: {c}, " # Initialize logging string
cp_end = self.opts.gp - 1 # Set the end index for this job
self.model.progress.increment() # Increment progress counter for this model

# Define helper functions to handle jump, bypass, and early exit scenarios
def do_jump(i, jump):
return min(jump, abs(cp_end - i))

def bypass_range(i):
if i == 0:
return range(c[i], c[i] + 1)
else:
return range(c[i], c[i] + b[i] + 1)

def early_exit_range(i):
if i == 0:
return range(c[i], c[i] + 1)
else:
return range(c[i], cp_end)

# Check if flag is enabled and if the current job has a flag set
if self.opts.flag and self.flag.get(c) != 0 and jump == 0:
# If jump is not set and there's a flag for this job, set jump
jump = do_jump(c[0] - 1, self.flag.get(c))

# If jump is set, skip to the next iteration of the loop
if jump > 0:
jump = jump - 1
continue

# Log model progress for each objective
for o in self.model.iter_obj2:
log += f"e{o + 1}: {self.model.e[o, c[o]]}, "
self.model.model.e[o + 2] = self.model.e[o, c[o]]

# Activate objective 0 and solve the model
self.model.obj_activate(0)
self.model.solve()
self.model.models_solved.increment()

# Check if early exit is enabled and if the model is infeasible
if self.opts.early_exit and self.model.is_infeasible():
# If so, increment infeasibilities counter
self.model.infeasibilities.increment()

# Set flag if flag is enabled
if self.opts.flag:
self.flag.set(early_exit_range, self.opts.gp, self.model.iter_obj2)

jump = do_jump(c[0], self.opts.gp) # Set jump
log += "infeasible" # Log infeasibility

# Log progress if process logging is enabled
if self.opts.process_logging:
self.logger.info(log)

continue # Skip to next iteration of loop

# Calculate slack values and set jump if bypass is enabled
elif self.opts.bypass and self.model.is_optimal():
b = []
for i in self.model.iter_obj2:
step = self.model.obj_range[i] / (self.opts.gp - 1)
slack = round(self.model.slack_val(i + 1))
b.append(int(slack / step))

# Log jump and set flag if enabled
log += f"jump: {b[0]}, "
if self.opts.flag:
self.flag.set(bypass_range, b[0] + 1, self.model.iter_obj2)
jump = do_jump(c[0], b[0])

# If model is optimal, calculate and log solutions
sols = []
if self.model.is_optimal():
sols.append(
self.model.obj_val(0)
- self.opts.eps
* sum(
10 ** (-1 * (o)) * self.model.slack_val(o + 1) / self.model.obj_range[o]
for o in self.model.iter_obj2
)
)

for o in self.model.iter_obj2:
sols.append(self.model.obj_val(o + 1))
for o in self.model.iter_obj2:
sols.append(self.model.obj_val(o + 1))

# Put results into queue as a dictionary
sols_dict = {tuple(sols): self.model.get_vars()}
self.queues.put_result(sols_dict)
# Put results into queue as a dictionary
sols_dict = {tuple(sols): self.model.get_vars()}
self.queues.put_result(sols_dict)

# Log solutions if process logging is enabled
log += f"solutions: {sols}"
if self.opts.process_logging:
self.logger.info(log)
# Log solutions if process logging is enabled
log += f"solutions: {sols}"
if self.opts.process_logging:
self.logger.info(log)

0 comments on commit 2bc2e0a

Please sign in to comment.