nmrproject/ILP/caffeinesynthesis.py
kilian 20824b6400 Dateien nach "ILP" hochladen
Now ILP solver picks optimal combination of two different similarities and similarity can also be calcuated using the mean of similarity instead of the comparitive value
2026-06-24 11:29:14 +02:00

192 lines
7.0 KiB
Python

import gurobipy as gp
from gurobipy import GRB, Model, quicksum
HYPEREDGES = {
1: ([], ['Xanthine']),
2: (['Xanthine'], ['p_{0,0}']),
3: (['Xanthine'], ['p_{0,1}']),
4: (['Xanthine'], ['p_{0,2}']),
5: (['p_{0,0}'], ['p_{0,3}']),
6: (['p_{0,0}'], ['p_{0,4}']),
7: (['p_{0,1}'], ['p_{0,3}']),
8: (['p_{0,1}'], ['p_{0,5}']),
9: (['p_{0,2}'], ['p_{0,4}']),
10: (['p_{0,2}'], ['p_{0,5}']),
11: (['p_{0,3}'], ['Caffeine']),
12: (['p_{0,4}'], ['Caffeine']),
13: (['p_{0,5}'], ['Caffeine']),
14: (['Caffeine'], []),
}
#Similyrity of Nodes NMR to Measured NMR
#Can how to add Values along a Path?
#Can you count position on path?
#Can you save spectra values to add hypergraphposition to spectrainformation?
#Compositespectra vs oredered set of spectra
VERTICES1 = {
1: ([0, 0], ['Xanthine']),
2: ([0, 0], ['p_{0,0}']),
3: ([0, 0], ['p_{0,1}']),
4: ([1, 0], ['p_{0,2}']),
5: ([0, 0], ['p_{0,3}']),
6: ([0, 0], ['p_{0,4}']),
7: ([0, 1], ['p_{0,5}']),
8: ([0, 0], ['Caffeine']),
}
#25014CX3
#03
VERTICES2 = {
1: ([0], ['Xanthine']),
2: ([0], ['p_{0,0}']),
3: ([0], ['p_{0,1}']),
4: ([1], ['p_{0,2}']),
5: ([0], ['p_{0,3}']),
6: ([0], ['p_{0,4}']),
7: ([1], ['p_{0,5}']),
8: ([0], ['Caffeine']),
}
VERTICES = ['Xanthine', 'p_{0,0}', 'p_{0,1}', 'p_{0,2}', 'p_{0,3}', 'p_{0,4}', 'p_{0,5}', 'Caffeine']
NMRLIKELYHOODS = [0.0, 0.2, 0.7, 0.1, 0.1, 0.2, 0.7, 0.0]
NMRLIKELYHOODS1 = [0.54, 0.52, 0.43, 0.62, 0.52, 0.56, 0.48, 0.5]
NMRLIKELYHOODS2 = [0.52, 0.52, 0.52, 0.61, 0.52, 0.56, 0.61, 0.59]
NMRLIKELYHOODS3 = [0.5, 0.53, 0.59, 0.59, 0.53, 0.56, 0.68, 0.62]
FIXED_FLOWS = {
1: 1,
14: 1,
}
def build_model(name, hyperedges, vertices, nmrlikelihoods1, nmrlikelihoods2, nmrlikelihoods3, 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}
n1 = model.addVars(vertices, vtype=GRB.CONTINUOUS, lb = 0.0, ub = 1.0, name = "nmr1")
n2 = model.addVars(vertices, vtype=GRB.CONTINUOUS, lb = 0.0, ub = 1.0, name = "nmr2")
n3 = model.addVars(vertices, vtype=GRB.CONTINUOUS, lb = 0.0, ub = 1.0, name = "nmr3")
c1 = model.addVars(vertices, vtype = GRB.BINARY, name = "n1_choice")
c2 = model.addVars(vertices, vtype = GRB.BINARY, name = "n2_choice")
c3 = model.addVars(vertices, vtype = GRB.BINARY, name = "n3_choice")
for v, nmr in zip(vertices, nmrlikelihoods1):
n1[v] = nmr
#print(f'Vertice: {v}, Similarity: {n1[v]}')
for v, nmr in zip(vertices, nmrlikelihoods2):
n2[v] = nmr
for v, nmr in zip(vertices, nmrlikelihoods3):
n3[v] = nmr
vertices = set(v for tails, heads in hyperedges.values() for v in tails + heads)
for v in vertices:
inflow = quicksum(x[e_id] for e_id, (_, heads) in hyperedges.items() if v in heads)
outflow = quicksum(x[e_id] for e_id, (tails, _) in hyperedges.items() if v in tails)
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}")
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}")
reaction_path = {}
if excluded_support:
model.addConstr(quicksum(b[e_id] for e_id in excluded_support) <= len(excluded_support) - 1, name = "different_hyperedges",)
#Multiplizier den node Wert mit infow + outflow
model.ModelSense = GRB.MAXIMIZE
#Multiply with a list of binarys where only one value is one and the rest zero and not both the same position
'''
model.setObjectiveN(
quicksum(n1[v_id] * c1[v_id] for v_id in vertices if v_id != [])
+ quicksum(n3[v_id] * c3[v_id] for v_id in vertices if v_id != []),
index = 0,
priority = 2,
name = "maximize_nmr_similarity",
)
'''
#Multiply node value with infow or outflow
'''
model.setObjectiveN(
quicksum(n1[t_id[0]] * c1[t_id[0]] * x[e_id] for e_id, (_, t_id) in hyperedges.items() if t_id != [])
+quicksum(n3[t_id[0]] * c3[t_id[0]] * x[e_id] for e_id, (_, t_id) in hyperedges.items() if t_id != []),
index = 0,
priority = 2,
name = "maximize_nmr_similarity",
)
'''
#Hybrid of both above
model.setObjective(
quicksum(n1[t_id[0]] * c1[t_id[0]] * x[e_id] for e_id, (_, t_id) in hyperedges.items() if t_id != [])
+quicksum(n3[t_id[0]] * c3[t_id[0]] * x[e_id] for e_id, (_, t_id) in hyperedges.items() if t_id != []),
sense = GRB.MAXIMIZE,
)
model.addConstr(gp.quicksum(c1[v_id] for v_id in vertices) == 1)
model.addConstr(gp.quicksum(c3[v_id] for v_id in vertices) == 1)
for v_id in vertices:
model.addConstr(c1[v_id] + c3[v_id] <= 1)
model.addConstr(gp.quicksum(x[e_id] for e_id, (_, t_id) in hyperedges.items()) == 5)
''''
model.setObjectiveN(
quicksum(-1 *b[e_id] for e_id in hyperedges),
index=1,
priority=1,
name="minimize_used_hyperedges",
)
'''
return model, x, b
def positive_entries(variable_dict, threshold = 0.5):
return {e_id: var.X for e_id, var in variable_dict.items() if var.X > threshold}
def print_solution(title, flow_solution, binary_solution, 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}, Tails = {tails}, Heads = {heads}")
print("\nBinary Variables:")
for e_id in sorted(binary_solution):
print(f"Binary Variable b_{e_id} = {binary_solution[e_id]}")
print(f"\nTotal flow: {sum(flow_solution.values())}")
print(f"Number of used hyperedges: {len(binary_solution)}")
def main():
model, x, b = build_model("HypergraphFlow", HYPEREDGES, VERTICES, NMRLIKELYHOODS1, NMRLIKELYHOODS2, NMRLIKELYHOODS3)
model.optimize()
if model.status != GRB.Status.OPTIMAL:
print("No optimal solution found for the first model.")
return
optimal_solution = positive_entries(x)
optimal_binary_solution = positive_entries(b)
print_solution("Optimal Solution", optimal_solution, optimal_binary_solution, HYPEREDGES)
""" excluded_support = list(optimal_binary_solution.keys())
second_model, x2, b2 = build_model("SecondBestHypergraphFlow", HYPEREDGES, excluded_support=excluded_support,)
second_model.optimize()
if second_model.status == GRB.Status.OPTIMAL:
second_solution = positive_entries(x2)
second_binary_solution = positive_entries(b2)
print_solution("Second Best Solution", second_solution, second_binary_solution, HYPEREDGES, VERTICES)
else:
print("No optimal solution found for the second best model.")
"""
if __name__ == "__main__":
main()