Repository navigation
Expand file tree
/
Copy pathbacktracking.py
More file actions
141 lines (105 loc) · 4.15 KB
/
Copy pathbacktracking.py
File metadata and controls
141 lines (105 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 13 15:52:32 2024
@author: md1621
"""
import numpy as np
import time
def make_matrix(rows, cols):
starting_matrix = [[9 for _ in range(cols)] for _ in range(rows)]
return np.array(starting_matrix)
def find_empty(matrix):
for i in range(len(matrix)):
for j in range(len(matrix[0])):
if matrix[i][j] == 9:
return (i, j) # row, col
return None
def sum_pos_neg_excluding_nine(arr):
sum_negative = sum(value for value in arr if value < 0)
sum_positive = sum(value for value in arr if value > 0 and value != 9)
return sum_negative, sum_positive
def cumulative_sum(arr):
cum_sum = []
cum_sum.append(arr[0])
total = 0
# Iterate over the original array, summing as we go
for num in arr:
total += num
cum_sum.append(total)
return np.array(cum_sum[1:])
def is_valid(matrix, stoichiometry, intermediate, product, reactant):
if not len(matrix[0]) == len(stoichiometry):
raise AssertionError('Stoichiometry and matrix generated do not match.')
for i in range(len(matrix)):
sum_negative, sum_positive = sum_pos_neg_excluding_nine(matrix[i])
if sum_negative < -2 or sum_positive > 2:
return False
if not any(9 in row for row in matrix) == True:
for i in range(len(matrix)):
sum_negative, sum_positive = sum_pos_neg_excluding_nine(matrix[i])
if sum_negative == 0 or sum_positive == 0:
return False
if not any(9 in row for row in matrix) == True:
matrix_stoich = np.sum(matrix, axis=0)
if np.all(matrix_stoich == stoichiometry) == False:
return False
for i in range(intermediate, np.shape(matrix)[1]):
array = matrix[:, i]
cumulative = cumulative_sum(array)
if np.all(cumulative >= 0) == False or np.all(cumulative == 0) == True:
return False
for i in range(product, intermediate):
array = matrix[:, i]
cumulative = cumulative_sum(array)
if np.all(cumulative >= 0) == False:
return False
for i in range(reactant, product):
array = matrix[:, i]
cumulative = cumulative_sum(array)
if np.all(cumulative >= stoichiometry[i]) == False:
return False
return True
def solve(matrix, stoichiometry, intermediate, product, reactant, time_budget, \
solutions=None, count=[0]):
start = time.time()
if solutions is None:
solutions = []
find = find_empty(matrix)
if not find:
if is_valid(matrix, stoichiometry, intermediate, product, reactant):
solutions.append(np.copy(matrix))
return solutions, count[0]
row, col = find
for i in range(-2, 3): # From -2 to 2 inclusive.
matrix[row][col] = i
end = time.time()
if end - start > time_budget:
print('Time budget reached!')
return solutions, count[0]
if is_valid(matrix, stoichiometry, intermediate, product, reactant):
count[0] += 1 # Increment the counter when is_valid is called.
_solutions, _ = solve(matrix, stoichiometry, intermediate, product, \
reactant, time_budget, solutions, count)
matrix[row][col] = 9 # Backtrack.
return solutions, count[0]
# Example usage:
hi = time.time()
elementary_reactions = 3
number_species = 5
matrix = make_matrix(elementary_reactions, number_species)
stoichiometry = [-1, 2, 1, 0, 0]
intermediate = 3
product = 1
reactant = 0
time_budget = 300
solutions, count = solve(matrix, stoichiometry, intermediate, product, reactant, time_budget)
for solution in solutions:
print(solution)
print('----------------------------')
print('Number of solutions found: ', len(solutions))
print('Total number of possible matrices: ', 5**(elementary_reactions * number_species))
print('Number of matrices checked: ', count)
print('Percentage of space checked: ', (count * 100) / 5**(elementary_reactions * number_species), '%')
bye = time.time()
print('Time spent: ', bye - hi, 's')