Skip to content

Commit 3551f3d

Browse files
authored
Merge pull request #13 from wouterbles/1.0.2
Release 1.0.2
2 parents a2465b5 + d404876 commit 3551f3d

File tree

4 files changed

+113
-108
lines changed

4 files changed

+113
-108
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 1.0.2
4+
5+
- Update dependencies
6+
37
## 1.0.1
48

59
- Make QueueHandler work on MacOS #5, thanks @yvanoers

pyaugmecon/queue_handler.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ def get_work(self, i):
6060
try:
6161
return self.job_qs[i].get_nowait() # Try to get the work for a given process without blocking
6262
except queue.Empty: # If the queue is empty
63-
if self.opts.redivide_work and self.get_longest_q() is not None:
63+
longest_q = self.get_longest_q() # Get the index of the job queue with the most items
64+
if self.opts.redivide_work and longest_q is not None:
6465
# If the `redivide_work` flag is set to True and there is work available, redivide the work
65-
return self.get_work(self.get_longest_q())
66+
return self.get_work(longest_q)
6667
if self.opts.process_logging:
6768
# If process logging is enabled, log that the process exited
6869
self.logger.info(f"PID: {i} exited")
@@ -128,6 +129,4 @@ def split_work(self):
128129

129130
for i, block in enumerate(blocks):
130131
items = [tuple(item) for sublist in block.tolist() for item in sublist] # Flatten the sub-blocks
131-
# Put the flattened items in the job queue for the process
132-
for t in items:
133-
self.job_qs[i].put(t)
132+
self.job_qs[i].put(items) # Put the flattened items in the job queue for the process

pyaugmecon/solver_process.py

Lines changed: 97 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -58,106 +58,107 @@ def run(self):
5858

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

64-
# If no more jobs, break the loop
65-
if not c:
64+
# If no more work, break the loop
65+
if not work:
6666
break
6767

68-
# Process the job
69-
log = f"Process: {self.p_num}, index: {c}, " # Initialize logging string
70-
cp_end = self.opts.gp - 1 # Set the end index for this job
71-
self.model.progress.increment() # Increment progress counter for this model
72-
73-
# Define helper functions to handle jump, bypass, and early exit scenarios
74-
def do_jump(i, jump):
75-
return min(jump, abs(cp_end - i))
76-
77-
def bypass_range(i):
78-
if i == 0:
79-
return range(c[i], c[i] + 1)
80-
else:
81-
return range(c[i], c[i] + b[i] + 1)
82-
83-
def early_exit_range(i):
84-
if i == 0:
85-
return range(c[i], c[i] + 1)
86-
else:
87-
return range(c[i], cp_end)
88-
89-
# Check if flag is enabled and if the current job has a flag set
90-
if self.opts.flag and self.flag.get(c) != 0 and jump == 0:
91-
# If jump is not set and there's a flag for this job, set jump
92-
jump = do_jump(c[0] - 1, self.flag.get(c))
93-
94-
# If jump is set, skip to the next iteration of the loop
95-
if jump > 0:
96-
jump = jump - 1
97-
continue
98-
99-
# Log model progress for each objective
100-
for o in self.model.iter_obj2:
101-
log += f"e{o + 1}: {self.model.e[o, c[o]]}, "
102-
self.model.model.e[o + 2] = self.model.e[o, c[o]]
103-
104-
# Activate objective 0 and solve the model
105-
self.model.obj_activate(0)
106-
self.model.solve()
107-
self.model.models_solved.increment()
108-
109-
# Check if early exit is enabled and if the model is infeasible
110-
if self.opts.early_exit and self.model.is_infeasible():
111-
# If so, increment infeasibilities counter
112-
self.model.infeasibilities.increment()
113-
114-
# Set flag if flag is enabled
115-
if self.opts.flag:
116-
self.flag.set(early_exit_range, self.opts.gp, self.model.iter_obj2)
117-
118-
jump = do_jump(c[0], self.opts.gp) # Set jump
119-
log += "infeasible" # Log infeasibility
120-
121-
# Log progress if process logging is enabled
122-
if self.opts.process_logging:
123-
self.logger.info(log)
124-
125-
continue # Skip to next iteration of loop
126-
127-
# Calculate slack values and set jump if bypass is enabled
128-
elif self.opts.bypass and self.model.is_optimal():
129-
b = []
130-
for i in self.model.iter_obj2:
131-
step = self.model.obj_range[i] / (self.opts.gp - 1)
132-
slack = round(self.model.slack_val(i + 1))
133-
b.append(int(slack / step))
134-
135-
# Log jump and set flag if enabled
136-
log += f"jump: {b[0]}, "
137-
if self.opts.flag:
138-
self.flag.set(bypass_range, b[0] + 1, self.model.iter_obj2)
139-
jump = do_jump(c[0], b[0])
140-
141-
# If model is optimal, calculate and log solutions
142-
sols = []
143-
if self.model.is_optimal():
144-
sols.append(
145-
self.model.obj_val(0)
146-
- self.opts.eps
147-
* sum(
148-
10 ** (-1 * (o)) * self.model.slack_val(o + 1) / self.model.obj_range[o]
149-
for o in self.model.iter_obj2
68+
# Process each job in the work list
69+
for c in work:
70+
log = f"Process: {self.p_num}, index: {c}, " # Initialize logging string
71+
cp_end = self.opts.gp - 1 # Set the end index for this job
72+
self.model.progress.increment() # Increment progress counter for this model
73+
74+
# Define helper functions to handle jump, bypass, and early exit scenarios
75+
def do_jump(i, jump):
76+
return min(jump, abs(cp_end - i))
77+
78+
def bypass_range(i):
79+
if i == 0:
80+
return range(c[i], c[i] + 1)
81+
else:
82+
return range(c[i], c[i] + b[i] + 1)
83+
84+
def early_exit_range(i):
85+
if i == 0:
86+
return range(c[i], c[i] + 1)
87+
else:
88+
return range(c[i], cp_end)
89+
90+
# Check if flag is enabled and if the current job has a flag set
91+
if self.opts.flag and self.flag.get(c) != 0 and jump == 0:
92+
# If jump is not set and there's a flag for this job, set jump
93+
jump = do_jump(c[0] - 1, self.flag.get(c))
94+
95+
# If jump is set, skip to the next iteration of the loop
96+
if jump > 0:
97+
jump = jump - 1
98+
continue
99+
100+
# Log model progress for each objective
101+
for o in self.model.iter_obj2:
102+
log += f"e{o + 1}: {self.model.e[o, c[o]]}, "
103+
self.model.model.e[o + 2] = self.model.e[o, c[o]]
104+
105+
# Activate objective 0 and solve the model
106+
self.model.obj_activate(0)
107+
self.model.solve()
108+
self.model.models_solved.increment()
109+
110+
# Check if early exit is enabled and if the model is infeasible
111+
if self.opts.early_exit and self.model.is_infeasible():
112+
# If so, increment infeasibilities counter
113+
self.model.infeasibilities.increment()
114+
115+
# Set flag if flag is enabled
116+
if self.opts.flag:
117+
self.flag.set(early_exit_range, self.opts.gp, self.model.iter_obj2)
118+
119+
jump = do_jump(c[0], self.opts.gp) # Set jump
120+
log += "infeasible" # Log infeasibility
121+
122+
# Log progress if process logging is enabled
123+
if self.opts.process_logging:
124+
self.logger.info(log)
125+
126+
continue # Skip to next iteration of loop
127+
128+
# Calculate slack values and set jump if bypass is enabled
129+
elif self.opts.bypass and self.model.is_optimal():
130+
b = []
131+
for i in self.model.iter_obj2:
132+
step = self.model.obj_range[i] / (self.opts.gp - 1)
133+
slack = round(self.model.slack_val(i + 1))
134+
b.append(int(slack / step))
135+
136+
# Log jump and set flag if enabled
137+
log += f"jump: {b[0]}, "
138+
if self.opts.flag:
139+
self.flag.set(bypass_range, b[0] + 1, self.model.iter_obj2)
140+
jump = do_jump(c[0], b[0])
141+
142+
# If model is optimal, calculate and log solutions
143+
sols = []
144+
if self.model.is_optimal():
145+
sols.append(
146+
self.model.obj_val(0)
147+
- self.opts.eps
148+
* sum(
149+
10 ** (-1 * (o)) * self.model.slack_val(o + 1) / self.model.obj_range[o]
150+
for o in self.model.iter_obj2
151+
)
150152
)
151-
)
152153

153-
for o in self.model.iter_obj2:
154-
sols.append(self.model.obj_val(o + 1))
154+
for o in self.model.iter_obj2:
155+
sols.append(self.model.obj_val(o + 1))
155156

156-
# Put results into queue as a dictionary
157-
sols_dict = {tuple(sols): self.model.get_vars()}
158-
self.queues.put_result(sols_dict)
157+
# Put results into queue as a dictionary
158+
sols_dict = {tuple(sols): self.model.get_vars()}
159+
self.queues.put_result(sols_dict)
159160

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

setup.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def get_long_description() -> str:
1717

1818
setup(
1919
name="pyaugmecon",
20-
version="1.0.1",
20+
version="1.0.2",
2121
author="Wouter Bles",
2222
author_email="[email protected]",
2323
long_description=get_long_description(),
@@ -38,6 +38,7 @@ def get_long_description() -> str:
3838
"Programming Language :: Python :: 3.8",
3939
"Programming Language :: Python :: 3.9",
4040
"Programming Language :: Python :: 3.10",
41+
"Programming Language :: Python :: 3.11",
4142
"Programming Language :: Python :: 3 :: Only",
4243
"Natural Language :: English",
4344
"Topic :: Scientific/Engineering",
@@ -47,11 +48,11 @@ def get_long_description() -> str:
4748
test_suite="tests",
4849
python_requires=">=3.8",
4950
install_requires=[
50-
"pyomo>=6.4,<6.5",
51-
"numpy>=1.2,<1.25",
52-
"pandas>=1.2,<1.6",
53-
"cloudpickle>=2.0,<2.3",
54-
"pymoo>=0.6,<0.7",
55-
"openpyxl>=3.0,<3.1",
51+
"pyomo~=6.6.1",
52+
"numpy~=1.25.2",
53+
"pandas~=2.0.3",
54+
"cloudpickle~=2.2.1",
55+
"pymoo~=0.6.0.1",
56+
"openpyxl~=3.1.2",
5657
],
5758
)

0 commit comments

Comments
 (0)