DmitrMakeev commited on
Commit
469d0b8
·
verified ·
1 Parent(s): f834392

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -66
app.py CHANGED
@@ -732,9 +732,7 @@ EC_COEFFICIENTS = {
732
  class NutrientCalculator:
733
  def __init__(self, volume_liters=1.0):
734
  self.volume = volume_liters
735
- self.results = {}
736
  self.target_profile = BASE_PROFILE.copy()
737
- self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
738
  self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
739
  self.total_ec = 0.0
740
 
@@ -752,81 +750,91 @@ class NutrientCalculator:
752
  # Список всех удобрений
753
  self.fertilizer_list = list(self.fertilizers.keys())
754
 
755
- def _label(self, element):
756
- """Форматирование названий элементов для вывода"""
757
- labels = {
758
- 'N (NO3-)': 'NO3',
759
- 'N (NH4+)': 'NH4'
760
- }
761
- return labels.get(element, element)
762
-
763
  def calculate(self):
764
  try:
765
- max_attempts = 100 # Максимальное количество попыток
766
- attempt = 0
767
- while attempt < max_attempts:
768
- attempt += 1
769
- print(f"Попытка {attempt} из {max_attempts}")
 
 
 
 
 
770
 
771
- # Генерация случайного порядка удобрений
772
- fertilizer_order = self._shuffle_fertilizers()
 
773
 
774
- # Сброс фактического профиля
775
- self._reset_actual_profile()
 
 
 
776
 
777
- # Пробуем рассчитать с текущим порядком удобрений
778
- if self._try_combination(fertilizer_order):
779
- print("Успешная комбинация найдена!")
780
- return self.results
781
 
782
- raise ValueError("Не удалось найти подходящую комбинацию удобрений после максимального количества попыток.")
 
 
783
 
784
- except Exception as e:
785
- print(f"Ошибка при расчёте: {str(e)}")
786
- raise
787
 
788
- def _shuffle_fertilizers(self):
789
- """Генерация случайного порядка удобрений"""
790
- return list(itertools.permutations(self.fertilizer_list))[hash(str(self.target_profile)) % len(self.fertilizer_list)]
791
 
792
- def _reset_actual_profile(self):
793
- """Сброс фактического профиля перед новой попыткой"""
794
- self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
795
- self.total_ec = 0.0
796
- self.results = {}
 
 
 
 
797
 
798
- def _try_combination(self, fertilizer_order):
799
- """Попытка расчета с заданным порядком удобрений"""
800
- for fert_name in fertilizer_order:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
801
  for element, content in self.fertilizers[fert_name].items():
802
- required_ppm = self.target_profile[element] - self.actual_profile[element]
803
- if required_ppm > 0.1:
804
- grams = (required_ppm * self.volume) / (content * 1000)
805
-
806
- if fert_name not in self.results:
807
- self.results[fert_name] = {
808
- 'граммы': 0.0,
809
- 'миллиграммы': 0,
810
- 'вклад в EC': 0.0
811
- }
812
- for elem in self.fertilizers[fert_name]:
813
- self.results[fert_name][f'внесет {self._label(elem)}'] = 0.0
814
-
815
- self.results[fert_name]['граммы'] += grams
816
- self.results[fert_name]['миллиграммы'] += int(grams * 1000)
817
-
818
- fert_ec = 0.0
819
- for elem, percent in self.fertilizers[fert_name].items():
820
- added_ppm = (grams * percent * 1000) / self.volume
821
- self.results[fert_name][f'внесет {self._label(elem)}'] += added_ppm
822
- self.actual_profile[elem] += added_ppm
823
- fert_ec += added_ppm * EC_COEFFICIENTS.get(elem, 0.0015)
824
-
825
- self.results[fert_name]['вклад в EC'] += fert_ec
826
- self.total_ec += fert_ec
827
-
828
- # Проверка результатов
829
- return self.validate_results()
830
 
831
  def validate_results(self):
832
  """Проверка соответствия целевым значениям"""
 
732
  class NutrientCalculator:
733
  def __init__(self, volume_liters=1.0):
734
  self.volume = volume_liters
 
735
  self.target_profile = BASE_PROFILE.copy()
 
736
  self.fertilizers = NUTRIENT_CONTENT_IN_FERTILIZERS
737
  self.total_ec = 0.0
738
 
 
750
  # Список всех удобрений
751
  self.fertilizer_list = list(self.fertilizers.keys())
752
 
 
 
 
 
 
 
 
 
753
  def calculate(self):
754
  try:
755
+ # Инициализация фактического профиля и результата
756
+ self.actual_profile = {k: 0.0 for k in self.target_profile}
757
+ self.results = {}
758
+
759
+ # Начинаем рекурсивный поиск
760
+ if self._backtrack_search():
761
+ print("Успешная комбинация найдена!")
762
+ return self.results
763
+ else:
764
+ raise ValueError("Не удалось найти подходящую комбинацию удобрений.")
765
 
766
+ except Exception as e:
767
+ print(f"Ошибка при расчёте: {str(e)}")
768
+ raise
769
 
770
+ def _backtrack_search(self, fertilizer_index=0):
771
+ """Рекурсивный поиск с возвратом"""
772
+ # Проверяем, достигнуты ли целевые значения
773
+ if self.validate_results():
774
+ return True
775
 
776
+ # Если перебор, откатываемся назад
777
+ if self._is_overage():
778
+ return False
 
779
 
780
+ # Пробуем добавить удобрения по очереди
781
+ for i in range(fertilizer_index, len(self.fertilizer_list)):
782
+ fert_name = self.fertilizer_list[i]
783
 
784
+ # Применяем удобрение
785
+ self._apply_fertilizer(fert_name)
 
786
 
787
+ print(f"Добавлено удобрение: {fert_name}")
 
 
788
 
789
+ # Рекурсивно пробуем следующее удобрение
790
+ if self._backtrack_search(i + 1):
791
+ return True
792
+
793
+ # Откатываемся назад (удаляем последнее удобрение)
794
+ self._remove_fertilizer(fert_name)
795
+ print(f"Откат: удалено удобрение {fert_name}")
796
+
797
+ return False
798
 
799
+ def _apply_fertilizer(self, fert_name):
800
+ """Применение удобрения"""
801
+ if fert_name not in self.results:
802
+ self.results[fert_name] = {
803
+ 'граммы': 0.0,
804
+ 'миллиграммы': 0,
805
+ 'вклад в EC': 0.0
806
+ }
807
+ for elem in self.fertilizers[fert_name]:
808
+ self.results[fert_name][f'внесет {elem}'] = 0.0
809
+
810
+ for element, content in self.fertilizers[fert_name].items():
811
+ required_ppm = self.target_profile[element] - self.actual_profile[element]
812
+ if required_ppm > 0.1:
813
+ grams = (required_ppm * self.volume) / (content * 1000)
814
+ self.results[fert_name]['граммы'] += grams
815
+ self.results[fert_name]['миллиграммы'] += int(grams * 1000)
816
+
817
+ added_ppm = (grams * content * 1000) / self.volume
818
+ self.results[fert_name][f'внесет {element}'] += added_ppm
819
+ self.actual_profile[element] += added_ppm
820
+
821
+ def _remove_fertilizer(self, fert_name):
822
+ """Удаление удобрения"""
823
+ if fert_name in self.results:
824
+ grams = self.results[fert_name]['граммы']
825
  for element, content in self.fertilizers[fert_name].items():
826
+ added_ppm = (grams * content * 1000) / self.volume
827
+ self.actual_profile[element] -= added_ppm
828
+ del self.results[fert_name]
829
+
830
+ def _is_overage(self):
831
+ """Проверка на перебор"""
832
+ for element, target_value in self.target_profile.items():
833
+ actual_value = self.actual_profile[element]
834
+ if actual_value > target_value + 0.1: # Допустимая погрешность
835
+ print(f"Перебор: {element} (цель: {target_value:.2f}, фактически: {actual_value:.2f})")
836
+ return True
837
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
838
 
839
  def validate_results(self):
840
  """Проверка соответствия целевым значениям"""