Dateien nach "ILP/butadien" hochladen
This commit is contained in:
@@ -0,0 +1,523 @@
|
|||||||
|
import numpy as np
|
||||||
|
import gurobipy as gp
|
||||||
|
from gurobipy import GRB, Model, quicksum
|
||||||
|
|
||||||
|
HYPERGRAPH = {
|
||||||
|
0: (['Butadien'], []),
|
||||||
|
2: (['p_{0,0}'], []),
|
||||||
|
3: (['p_{0,1}'], []),
|
||||||
|
4: (['Butadien', 'Butadien'], ['p_{0,0}', 'p_{0,1}']),
|
||||||
|
6: (['p_{0,2}'], []),
|
||||||
|
7: (['Butadien', 'Butadien'], ['p_{0,2}']),
|
||||||
|
10: (['p_{0,0}', 'p_{0,1}'], ['Butadien', 'Butadien']),
|
||||||
|
12: (['p_{0,3}'], []),
|
||||||
|
13: (['p_{0,0}', 'p_{0,2}'], ['p_{0,3}']),
|
||||||
|
17: (['p_{0,4}'], []),
|
||||||
|
18: (['p_{0,1}', 'p_{0,1}'], ['Butadien', 'p_{0,4}']),
|
||||||
|
19: (['p_{0,5}'], []),
|
||||||
|
20: (['p_{0,1}', 'p_{0,2}'], ['Butadien', 'p_{0,5}']),
|
||||||
|
23: (['Butadien', 'p_{0,1}'], ['p_{0,0}', 'p_{0,4}']),
|
||||||
|
26: (['Butadien', 'p_{0,2}'], ['p_{0,0}', 'p_{0,5}']),
|
||||||
|
27: (['p_{0,6}'], []),
|
||||||
|
28: (['p_{0,0}', 'p_{0,1}'], ['p_{0,6}']),
|
||||||
|
29: (['p_{0,7}'], []),
|
||||||
|
30: (['Butadien', 'p_{0,0}'], ['p_{0,7}']),
|
||||||
|
31: (['p_{0,8}'], []),
|
||||||
|
32: (['Butadien', 'p_{0,1}'], ['p_{0,8}']),
|
||||||
|
33: (['Butadien', 'p_{0,1}'], ['p_{0,5}']),
|
||||||
|
34: (['p_{0,9}'], []),
|
||||||
|
35: (['Butadien', 'p_{0,1}'], ['p_{0,9}']),
|
||||||
|
36: (['p_{0,10}'], []),
|
||||||
|
37: (['Butadien', 'p_{0,1}'], ['p_{0,10}']),
|
||||||
|
38: (['p_{0,3}'], ['p_{0,0}', 'p_{0,2}']),
|
||||||
|
41: (['p_{0,11}'], []),
|
||||||
|
42: (['p_{0,4}'], ['p_{0,0}', 'p_{0,11}']),
|
||||||
|
43: (['p_{0,12}'], []),
|
||||||
|
44: (['p_{0,5}'], ['p_{0,12}']),
|
||||||
|
63: (['p_{0,13}'], []),
|
||||||
|
64: (['p_{0,4}', 'p_{0,6}'], ['p_{0,1}', 'p_{0,13}']),
|
||||||
|
65: (['p_{0,2}', 'p_{0,4}'], ['p_{0,1}', 'p_{0,5}']),
|
||||||
|
66: (['p_{0,0}', 'p_{0,4}'], ['Butadien', 'p_{0,1}']),
|
||||||
|
67: (['Butadien', 'p_{0,4}'], ['p_{0,1}', 'p_{0,1}']),
|
||||||
|
77: (['p_{0,5}', 'p_{0,6}'], ['p_{0,2}', 'p_{0,13}']),
|
||||||
|
79: (['p_{0,0}', 'p_{0,5}'], ['Butadien', 'p_{0,2}']),
|
||||||
|
80: (['Butadien', 'p_{0,5}'], ['p_{0,1}', 'p_{0,2}']),
|
||||||
|
83: (['p_{0,1}', 'p_{0,5}'], ['p_{0,2}', 'p_{0,4}']),
|
||||||
|
96: (['Butadien', 'p_{0,6}'], ['p_{0,0}', 'p_{0,13}']),
|
||||||
|
97: (['p_{0,1}', 'p_{0,6}'], ['Butadien', 'p_{0,13}']),
|
||||||
|
99: (['p_{0,14}'], []),
|
||||||
|
100: (['p_{0,0}', 'p_{0,6}'], ['p_{0,14}']),
|
||||||
|
101: (['p_{0,15}'], []),
|
||||||
|
102: (['p_{0,0}', 'p_{0,7}'], ['p_{0,15}']),
|
||||||
|
121: (['p_{0,0}', 'p_{0,4}'], ['p_{0,13}']),
|
||||||
|
122: (['p_{0,16}'], []),
|
||||||
|
123: (['p_{0,0}', 'p_{0,4}'], ['p_{0,16}']),
|
||||||
|
124: (['p_{0,17}'], []),
|
||||||
|
125: (['Butadien', 'p_{0,7}'], ['p_{0,17}']),
|
||||||
|
127: (['p_{0,12}'], ['p_{0,5}']),
|
||||||
|
130: (['p_{0,14}'], ['p_{0,0}', 'p_{0,6}']),
|
||||||
|
132: (['p_{0,15}'], ['p_{0,0}', 'p_{0,7}']),
|
||||||
|
135: (['p_{0,0}', 'p_{0,11}'], ['p_{0,4}']),
|
||||||
|
153: (['Butadien', 'p_{0,13}'], ['p_{0,1}', 'p_{0,6}']),
|
||||||
|
155: (['p_{0,0}', 'p_{0,13}'], ['Butadien', 'p_{0,6}']),
|
||||||
|
157: (['p_{0,1}', 'p_{0,13}'], ['p_{0,4}', 'p_{0,6}']),
|
||||||
|
158: (['p_{0,2}', 'p_{0,13}'], ['p_{0,5}', 'p_{0,6}']),
|
||||||
|
210: (['p_{0,18}'], []),
|
||||||
|
211: (['Butadien', 'p_{0,11}'], ['p_{0,18}']),
|
||||||
|
213: ([], ['Butadien']),
|
||||||
|
}
|
||||||
|
|
||||||
|
HYPERGRAPH2 = {
|
||||||
|
2: (['p_{0,0}'], []),
|
||||||
|
3: (['p_{0,1}'], []),
|
||||||
|
4: (['Butadien', 'Butadien'], ['p_{0,0}', 'p_{0,1}']),
|
||||||
|
6: (['p_{0,2}'], []),
|
||||||
|
7: (['Butadien', 'Butadien'], ['p_{0,2}']),
|
||||||
|
17: (['p_{0,4}'], []),
|
||||||
|
23: (['Butadien', 'p_{0,1}'], ['p_{0,0}', 'p_{0,4}']),
|
||||||
|
41: (['p_{0,11}'], []),
|
||||||
|
42: (['p_{0,4}'], ['p_{0,0}', 'p_{0,11}']),
|
||||||
|
213: ([], ['Butadien']),
|
||||||
|
}
|
||||||
|
|
||||||
|
HYPERGRAPH3 = {
|
||||||
|
0: (['Butadien'], []),
|
||||||
|
213: ([], ['Butadien']),
|
||||||
|
4: (['Butadien', 'Butadien'], ['p_{0,0}', 'Butadien']),
|
||||||
|
2: (['p_{0,0}'], []),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIXED_FLOWS = {
|
||||||
|
# three Butadiene molecules enter the network
|
||||||
|
213: 3,
|
||||||
|
|
||||||
|
# one benzene molecule leaves the network
|
||||||
|
41: 1,
|
||||||
|
|
||||||
|
# do not fix edge 4; otherwise part of the expected pathway is already given
|
||||||
|
# 4: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_model(name, hyperedges, vertices, vl1, vl2, vl3, excluded_support=None):
|
||||||
|
model = Model(name)
|
||||||
|
|
||||||
|
x = {
|
||||||
|
e_id: model.addVar(vtype=GRB.INTEGER, lb=0, name=f"x_{e_id}")
|
||||||
|
for e_id in hyperedges
|
||||||
|
}
|
||||||
|
b = {
|
||||||
|
e_id: model.addVar(vtype=GRB.BINARY, name=f"b_{e_id}")
|
||||||
|
for e_id in hyperedges
|
||||||
|
}
|
||||||
|
|
||||||
|
# NMR variables are now on molecules, not reaction edges
|
||||||
|
candidate_vertices = [v for v in vertices if v != "Butadien"]
|
||||||
|
|
||||||
|
n1 = {
|
||||||
|
v: model.addVar(vtype=GRB.BINARY, name=f"n1_{v}")
|
||||||
|
for v in candidate_vertices
|
||||||
|
}
|
||||||
|
n2 = {
|
||||||
|
v: model.addVar(vtype=GRB.BINARY, name=f"n2_{v}")
|
||||||
|
for v in candidate_vertices
|
||||||
|
}
|
||||||
|
n3 = {
|
||||||
|
v: model.addVar(vtype=GRB.BINARY, name=f"n3_{v}")
|
||||||
|
for v in candidate_vertices
|
||||||
|
}
|
||||||
|
|
||||||
|
all_vertices = set(
|
||||||
|
v
|
||||||
|
for tails, heads in hyperedges.values()
|
||||||
|
for v in tails + heads
|
||||||
|
)
|
||||||
|
|
||||||
|
# flow conservation, unchanged from the original model
|
||||||
|
for v in all_vertices:
|
||||||
|
inflow = quicksum(
|
||||||
|
x[e_id] * heads.count(v)
|
||||||
|
for e_id, (_, heads) in hyperedges.items()
|
||||||
|
)
|
||||||
|
outflow = quicksum(
|
||||||
|
x[e_id] * tails.count(v)
|
||||||
|
for e_id, (tails, _) in hyperedges.items()
|
||||||
|
)
|
||||||
|
model.addConstr(
|
||||||
|
inflow == outflow,
|
||||||
|
name=f"flow_conservation_{v}",
|
||||||
|
)
|
||||||
|
|
||||||
|
for e_id, value in FIXED_FLOWS.items():
|
||||||
|
model.addConstr(
|
||||||
|
x[e_id] == value,
|
||||||
|
name=f"fixed_flow_{e_id}",
|
||||||
|
)
|
||||||
|
|
||||||
|
# link integer flow x[e] and binary "reaction is used" variable b[e]
|
||||||
|
for e_id in hyperedges:
|
||||||
|
model.addGenConstrIndicator(
|
||||||
|
b[e_id],
|
||||||
|
0,
|
||||||
|
x[e_id] == 0,
|
||||||
|
name=f"unused_implies_zero_{e_id}",
|
||||||
|
)
|
||||||
|
model.addConstr(
|
||||||
|
x[e_id] >= b[e_id],
|
||||||
|
name=f"used_implies_positive_flow_{e_id}",
|
||||||
|
)
|
||||||
|
|
||||||
|
# each NMR observation is explained by one candidate molecule
|
||||||
|
model.addConstr(
|
||||||
|
quicksum(n1[v] for v in candidate_vertices) == 1,
|
||||||
|
name="one_molecule_for_nmr1",
|
||||||
|
)
|
||||||
|
model.addConstr(
|
||||||
|
quicksum(n2[v] for v in candidate_vertices) == 1,
|
||||||
|
name="one_molecule_for_nmr2",
|
||||||
|
)
|
||||||
|
model.addConstr(
|
||||||
|
quicksum(n3[v] for v in candidate_vertices) == 1,
|
||||||
|
name="one_molecule_for_nmr3",
|
||||||
|
)
|
||||||
|
|
||||||
|
# an NMR-supported molecule must actually be produced by a selected reaction
|
||||||
|
for v in candidate_vertices:
|
||||||
|
producing_edges = [
|
||||||
|
e_id
|
||||||
|
for e_id, (tails, heads) in hyperedges.items()
|
||||||
|
if tails != [] and v in heads
|
||||||
|
]
|
||||||
|
|
||||||
|
if producing_edges:
|
||||||
|
produced = quicksum(b[e_id] for e_id in producing_edges)
|
||||||
|
model.addConstr(
|
||||||
|
n1[v] <= produced,
|
||||||
|
name=f"nmr1_molecule_must_be_produced_{v}",
|
||||||
|
)
|
||||||
|
model.addConstr(
|
||||||
|
n2[v] <= produced,
|
||||||
|
name=f"nmr2_molecule_must_be_produced_{v}",
|
||||||
|
)
|
||||||
|
model.addConstr(
|
||||||
|
n3[v] <= produced,
|
||||||
|
name=f"nmr3_molecule_must_be_produced_{v}",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
model.addConstr(n1[v] == 0)
|
||||||
|
model.addConstr(n2[v] == 0)
|
||||||
|
model.addConstr(n3[v] == 0)
|
||||||
|
|
||||||
|
if excluded_support:
|
||||||
|
model.addConstr(
|
||||||
|
quicksum(b[e_id] for e_id in excluded_support)
|
||||||
|
<= len(excluded_support) - 1,
|
||||||
|
name="different_hyperedges",
|
||||||
|
)
|
||||||
|
|
||||||
|
# no direct forward/reverse reaction pairs
|
||||||
|
for e_id1, (tails1, heads1) in hyperedges.items():
|
||||||
|
for e_id2, (tails2, heads2) in hyperedges.items():
|
||||||
|
if e_id1 < e_id2 and (heads1, tails1) == (tails2, heads2):
|
||||||
|
model.addConstr(
|
||||||
|
b[e_id1] + b[e_id2] <= 1,
|
||||||
|
name=f"no_reverse_pair_{e_id1}_{e_id2}",
|
||||||
|
)
|
||||||
|
|
||||||
|
# NMR scores stay attached directly to candidate molecules
|
||||||
|
nmr_score = quicksum(
|
||||||
|
vl1[v] * n1[v] + vl2[v] * n2[v] + vl3[v] * n3[v]
|
||||||
|
for v in candidate_vertices
|
||||||
|
)
|
||||||
|
|
||||||
|
internal_edges = [
|
||||||
|
e_id
|
||||||
|
for e_id, (tails, heads) in hyperedges.items()
|
||||||
|
if tails != [] and heads != []
|
||||||
|
]
|
||||||
|
|
||||||
|
number_of_reactions = quicksum(
|
||||||
|
b[e_id] for e_id in internal_edges
|
||||||
|
)
|
||||||
|
|
||||||
|
total_internal_flow = quicksum(
|
||||||
|
x[e_id] for e_id in internal_edges
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
model,
|
||||||
|
x,
|
||||||
|
b,
|
||||||
|
n1,
|
||||||
|
n2,
|
||||||
|
n3,
|
||||||
|
nmr_score,
|
||||||
|
number_of_reactions,
|
||||||
|
total_internal_flow,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def optimize_model(
|
||||||
|
model,
|
||||||
|
nmr_score,
|
||||||
|
number_of_reactions,
|
||||||
|
total_internal_flow,
|
||||||
|
):
|
||||||
|
# 1. maximize NMR evidence
|
||||||
|
model.setObjective(nmr_score, GRB.MAXIMIZE)
|
||||||
|
model.optimize()
|
||||||
|
|
||||||
|
if model.status != GRB.Status.OPTIMAL:
|
||||||
|
return False
|
||||||
|
|
||||||
|
best_nmr = model.ObjVal
|
||||||
|
model.addConstr(
|
||||||
|
nmr_score >= best_nmr - 1e-8,
|
||||||
|
name="keep_best_nmr_score",
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. among equally good NMR solutions, use as few reactions as possible
|
||||||
|
model.setObjective(number_of_reactions, GRB.MINIMIZE)
|
||||||
|
model.optimize()
|
||||||
|
|
||||||
|
if model.status != GRB.Status.OPTIMAL:
|
||||||
|
return False
|
||||||
|
|
||||||
|
best_number_of_reactions = int(round(model.ObjVal))
|
||||||
|
model.addConstr(
|
||||||
|
number_of_reactions <= best_number_of_reactions,
|
||||||
|
name="keep_minimum_number_of_reactions",
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. then minimize total internal flow
|
||||||
|
model.setObjective(total_internal_flow, GRB.MINIMIZE)
|
||||||
|
model.optimize()
|
||||||
|
|
||||||
|
return model.status == GRB.Status.OPTIMAL
|
||||||
|
|
||||||
|
|
||||||
|
def positive_entries(variable_dict, threshold=0.5):
|
||||||
|
return {
|
||||||
|
key: var.X
|
||||||
|
for key, var in variable_dict.items()
|
||||||
|
if var.X > threshold
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def print_solution(
|
||||||
|
title,
|
||||||
|
flow_solution,
|
||||||
|
binary_solution,
|
||||||
|
nmr1_solution,
|
||||||
|
nmr2_solution,
|
||||||
|
nmr3_solution,
|
||||||
|
vertex1,
|
||||||
|
vertex2,
|
||||||
|
vertex3,
|
||||||
|
hyperedges,
|
||||||
|
):
|
||||||
|
print(f"\n{title}:")
|
||||||
|
|
||||||
|
for e_id in sorted(flow_solution):
|
||||||
|
flow = flow_solution[e_id]
|
||||||
|
tails, heads = hyperedges[e_id]
|
||||||
|
print(
|
||||||
|
f"Hyperedge {e_id}: Flow = {flow}, "
|
||||||
|
f"Tails = {tails}, Heads = {heads}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\nNMR assignments:")
|
||||||
|
for label, solution, scores in [
|
||||||
|
("NMR1", nmr1_solution, vertex1),
|
||||||
|
("NMR2", nmr2_solution, vertex2),
|
||||||
|
("NMR3", nmr3_solution, vertex3),
|
||||||
|
]:
|
||||||
|
for molecule in solution:
|
||||||
|
print(
|
||||||
|
f"{label}: {molecule}, "
|
||||||
|
f"similarity = {scores[molecule]:.4f}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"\nTotal flow: {sum(flow_solution.values())}")
|
||||||
|
print(f"Number of used hyperedges: {len(binary_solution)}")
|
||||||
|
|
||||||
|
|
||||||
|
def solve_once(
|
||||||
|
name,
|
||||||
|
hypergraph,
|
||||||
|
vertices,
|
||||||
|
vertex1,
|
||||||
|
vertex2,
|
||||||
|
vertex3,
|
||||||
|
excluded_support=None,
|
||||||
|
):
|
||||||
|
(
|
||||||
|
model,
|
||||||
|
x,
|
||||||
|
b,
|
||||||
|
n1,
|
||||||
|
n2,
|
||||||
|
n3,
|
||||||
|
nmr_score,
|
||||||
|
number_of_reactions,
|
||||||
|
total_internal_flow,
|
||||||
|
) = build_model(
|
||||||
|
name,
|
||||||
|
hypergraph,
|
||||||
|
vertices,
|
||||||
|
vertex1,
|
||||||
|
vertex2,
|
||||||
|
vertex3,
|
||||||
|
excluded_support=excluded_support,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not optimize_model(
|
||||||
|
model,
|
||||||
|
nmr_score,
|
||||||
|
number_of_reactions,
|
||||||
|
total_internal_flow,
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return (
|
||||||
|
model,
|
||||||
|
x,
|
||||||
|
b,
|
||||||
|
n1,
|
||||||
|
n2,
|
||||||
|
n3,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
VERTICES = [
|
||||||
|
'Butadien',
|
||||||
|
'p_{0,0}',
|
||||||
|
'p_{0,1}',
|
||||||
|
'p_{0,2}',
|
||||||
|
'p_{0,3}',
|
||||||
|
'p_{0,4}',
|
||||||
|
'p_{0,5}',
|
||||||
|
'p_{0,6}',
|
||||||
|
'p_{0,7}',
|
||||||
|
'p_{0,8}',
|
||||||
|
'p_{0,9}',
|
||||||
|
'p_{0,10}',
|
||||||
|
'p_{0,11}',
|
||||||
|
'p_{0,12}',
|
||||||
|
'p_{0,13}',
|
||||||
|
'p_{0,14}',
|
||||||
|
'p_{0,15}',
|
||||||
|
'p_{0,16}',
|
||||||
|
'p_{0,17}',
|
||||||
|
'p_{0,18}',
|
||||||
|
]
|
||||||
|
|
||||||
|
# same molecule similarities as in the current butadiensynthesis.py
|
||||||
|
# the difference is that they are used directly as molecule scores
|
||||||
|
|
||||||
|
# comparison with the NMR of ethylene and hexatriene
|
||||||
|
NMR1 = [
|
||||||
|
0.32, 0.5, 0.87, 0.0, 0.11, 0.58, 0.06, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 0.0, 0.0, 0.09, 0.0, 0.0, 0.17, 0.0, 0.09,
|
||||||
|
]
|
||||||
|
|
||||||
|
# comparison with the NMR of ethylene and octatriene
|
||||||
|
NMR2 = [
|
||||||
|
0.33, 0.43, 0.6, 0.0, 0.13, 0.9, 0.07, 0.01, 0.0, 0.0,
|
||||||
|
0.01, 0.0, 0.0, 0.01, 0.1, 0.0, 0.0, 0.22, 0.0, 0.13,
|
||||||
|
]
|
||||||
|
|
||||||
|
# comparison with the NMR of ethylene and benzene
|
||||||
|
NMR3 = [
|
||||||
|
0.0, 0.32, 0.0, 0.0, 0.0, 0.0, 0.05, 0.0, 0.0, 0.02,
|
||||||
|
0.0, 0.29, 0.95, 0.17, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05,
|
||||||
|
]
|
||||||
|
|
||||||
|
normalize = False
|
||||||
|
|
||||||
|
if normalize:
|
||||||
|
NMR1 = [value / sum(NMR1) for value in NMR1]
|
||||||
|
NMR2 = [value / sum(NMR2) for value in NMR2]
|
||||||
|
NMR3 = [value / sum(NMR3) for value in NMR3]
|
||||||
|
|
||||||
|
VERTICE1 = dict(zip(VERTICES, NMR1))
|
||||||
|
VERTICE2 = dict(zip(VERTICES, NMR2))
|
||||||
|
VERTICE3 = dict(zip(VERTICES, NMR3))
|
||||||
|
|
||||||
|
result = solve_once(
|
||||||
|
"HypergraphFlowSpeciesNMR",
|
||||||
|
HYPERGRAPH,
|
||||||
|
VERTICES,
|
||||||
|
VERTICE1,
|
||||||
|
VERTICE2,
|
||||||
|
VERTICE3,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result is None:
|
||||||
|
print("No optimal solution found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
model, x, b, n1, n2, n3 = result
|
||||||
|
|
||||||
|
optimal_solution = positive_entries(x)
|
||||||
|
optimal_binary_solution = positive_entries(b)
|
||||||
|
optimal_nmr1 = positive_entries(n1)
|
||||||
|
optimal_nmr2 = positive_entries(n2)
|
||||||
|
optimal_nmr3 = positive_entries(n3)
|
||||||
|
|
||||||
|
print_solution(
|
||||||
|
"Optimal Solution",
|
||||||
|
optimal_solution,
|
||||||
|
optimal_binary_solution,
|
||||||
|
optimal_nmr1,
|
||||||
|
optimal_nmr2,
|
||||||
|
optimal_nmr3,
|
||||||
|
VERTICE1,
|
||||||
|
VERTICE2,
|
||||||
|
VERTICE3,
|
||||||
|
HYPERGRAPH,
|
||||||
|
)
|
||||||
|
|
||||||
|
# optional second-best network support
|
||||||
|
excluded_support = list(optimal_binary_solution.keys())
|
||||||
|
|
||||||
|
result2 = solve_once(
|
||||||
|
"SecondBestHypergraphFlowSpeciesNMR",
|
||||||
|
HYPERGRAPH,
|
||||||
|
VERTICES,
|
||||||
|
VERTICE1,
|
||||||
|
VERTICE2,
|
||||||
|
VERTICE3,
|
||||||
|
excluded_support=excluded_support,
|
||||||
|
)
|
||||||
|
|
||||||
|
if result2 is None:
|
||||||
|
print("\nNo second solution found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
model2, x2, b2, n12, n22, n32 = result2
|
||||||
|
|
||||||
|
second_solution = positive_entries(x2)
|
||||||
|
second_binary_solution = positive_entries(b2)
|
||||||
|
second_nmr1 = positive_entries(n12)
|
||||||
|
second_nmr2 = positive_entries(n22)
|
||||||
|
second_nmr3 = positive_entries(n32)
|
||||||
|
|
||||||
|
print_solution(
|
||||||
|
"Second Best Solution",
|
||||||
|
second_solution,
|
||||||
|
second_binary_solution,
|
||||||
|
second_nmr1,
|
||||||
|
second_nmr2,
|
||||||
|
second_nmr3,
|
||||||
|
VERTICE1,
|
||||||
|
VERTICE2,
|
||||||
|
VERTICE3,
|
||||||
|
HYPERGRAPH,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user