<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
А обещали, что будет все понятно:-)
(1) karpik666, Я пошутил:)
Когда-то хотел реализовать симлекс метод для распределения затрат по белым фирмам из которой состоит серая фирма) …. хорошая вещь, скачаю, уверен найду где применить)
(3) sasha777666, Симплекс метод намного более производительный с точки зрения вычислений, но реализуется сложнее и оптимизирует только линейный функционал. Градиентный спуск намного проще и универсальнее и его главный недостаток — большая вычислительная емкость по мере развития железа становится все менее существенным.
Хм, это вроде еще методом наискорейшего спуска называют. Вроде если у нас несколько локальных экстремумов (н-р минимумов), то решение будет зависеть от начального приближения, а то все точки можем просто не найти (решение в первую же ближайшую ямку по градиенту попадёт). Даже на рисунке с диаграммой у вас есть что-то похожее на то, о чём я говорю.
(6) Идальго, Да — Вы правы. Проблему локальных минимумов (если они есть) данный метод оставляет открытой. Даже на картинке видно что метод «сползает» в один из возможных минимумов. Как вариант, конечно, можно строить несколько случайных опорных решений и сравнивать полученные минимумы на основе каждого из них. В конце концов механизм многопоточности позволит отработать параллельно несколько решений и с большей вероятностью найти именно глобальный минимум.
С другой стороны можно повысить качество опорного решения, приблизив его к глобальному минимуму. Есть эмпирическое соображение, что чем «глубже» яма тем круче у нее стенки, а следовательно уменьшение значения целевой функции идет быстрее. На основе этого соображения можно не искать множество минимумов, а создав некоторое количество опорных решений прогнать их на 5-10 итерациях, замерив относительную скорость сходимости для каждого. Много вычислительных ресурсов это не займет, но зато позволит выбрать самое перспективное из возможных опроных.
А можно воспользоваться и другими алгоритмами как выбора опорного решения, так и поиска глобального минимума. О которых собственно я еще планирую рассказать:)
Спасибо за ценное замечание!
Можно попробовать реализовать решение той же задачи генетическими алгоритмами. Та же беда с вычислительными ресурсами, зато, вроде как, решается проблема с локальными экстремумами при значительных выборках начальных популяций
(8) dumal, Генетический алгоритм, имхо, немного не про это. Генетика вообще не о рациональных числах:) Генетический алгоритм это про то как из конечного набора деталей (генов) сложить самую правильную конструкцию (организм). А вот на бесконечных полях действительных чисел с неограниченной точностью он теряется. Впрочем именно об этом и будет моя следующая статья. Там постараюсь объяснить и обосновать это подробнее.
(9) ildarovich перелогиньтесь =)
(10) Не согласен, у обоих свой оригинальный стиль и слог. Шутка не смешная
(11) Артано, может и не смешная. Просто при прочтении данной статьи я сравнивал не слог, а эмоции, которая она у меня вызывает, вот и не смог удержаться, так глупо пошутить:(
Нужно заметить, что при выборе «действительно малой» величины приращений dXn следует учитывать, что с ее уменьшением начинает расти погрешность вычислений из-за ограниченности разрядной сетки.
(13) Mr.Rm, В общем случае — да, однако, 0,00001 от 10 000 это совсем не то, что 0,00001 от 0,001. То есть величина относительного шага приращения Х для вычисления dXn с точки зрения возможной точности вычисления зависит не только от себя, но и от величины Х. Если копаться глубже, то правильный коэффициент приращения в зависимости от величины X, величин других переменных и характера целевой функции вычисляется как метрический тензор риманова пространства. Но в заголовок статьи я включил словосочетание «это просто», что до известной степени не позволило мне так сказать растечься во всю ширь и глубину проблемы:)
А замечание Ваше полезно. Спасибо!
Добрый вечер. В такого рода публикациях особенно полезны ссылки на литературу… Все-таки, не бытовым языком оперируете, и соответственно терминология не придуманная Вами и алгоритмы тоже. Реализация на 1с это другой момент, за это поставил + (хотя не качал 🙂 ). Но надо давать ссылки на литературу, ресурсы, тем более если планируете цикл статей.
(15) Yimaida, Спасибо за замечание. Учту на будущее и, возможно, добавлю ссылки к данной статье. Хотя рождению этой статьи предшествовала практическая и неоднократная реализация метода, поэтому собственно при написании статьи я не пользовался литературой. Взял готовый, опробованный и отточенный метод и описал как он работает по возможности понятным языком, не претендуя, естественно, на полный копирайт, но и не восстанавливая ретроспективно источники информации и чужие идеи, которые привели меня к данному решению…
С другой стороны, действительно, может показаться, что я выдаю себя за слишком умного, не приводя источников своей осведомленности и талантливости… Учту на будущее. Еще раз благодарю за замечание.
(16) Как раз, наоборот, сейчас придумать алгоритм оптимизации может любой программист, т.к. специфика работы располагает. Я нисколько не сомневаюсь, что метод мог быть разработан Вами. Я тоже не вспомню всю литературу, которую читал и изучал, но терминология в тексте выдает не оригинальность как минимум описания проблемы. Литература была бы полезна для более детального изучения проблемы и как хорошее дополнение к статье. Лично мне было бы приятно увидеть такие ссылки в конце статьи. Справедливости ради скажу, что на инфостарте есть статьи где авторы постарались и привели ссылки.
Про погрешности тоже справедливо было отмечено.
P.S. Всегда обращаю внимание на статьи по оптимизации, т.к. сам делал курсач на такую тему, и в живую столкнулся с ограничениями, которые нельзя обойти в реальных задачах (например, количество параметров «целевой функции»), а также поработал с литературой, хотя в курсе высшей математики преподают методы решения задач оптимизации.
P.P.S. Все замечания не в пику, а как взгляд со стороны 🙂
Добрый день.
Андрей, интересная статья. Наша компания сейчас как раз думает над тем, как на базе платформы 1С решить методом обобщенного градиента следующую задачу:
Есть несколько торговых точек, по каждой торговой точке есть данные о продажах, остатках, пороговых значениях запасов.
Ключевым показателем здесь являются Дни запаса товара на торговой точке.
Целевая функция — коэффициент вариации дней запаса по сети(отношение стандартного отклонения к среднему значению).
Необходимо найти такие значения запасов на торговых точках, чтобы коэффициент вариации дней запасов был минимальным.
При этом в задаче действуют следующие ограничения:
1. Сумма всех перераспределяемых запасов по сети равна суммарным остаткам в сети на текущий момент плюс остатки на центральном складе
2. Запасы могут принимать только целочисленные значения.
3. На каждой торговой точке запасы должны быть не меньше минимального порогового значения.
Андрей, Вам интересна такая задача? Смогли бы написать внешнюю обработку для её решения для платформы 1С Предприятие 8.3?
(18) Добрый день, Денис. Задача мне интересна. Но подробности я бы обсудил в личке:)
Андрей, подробности готов обсудить по почте — dsolovyov.tz@gmail.com