Prawie równomierny rozkład losowy.

0

Witam,

W każdym miesiącu chciałbym przeprowadzać audyt komputerów.
Ilość audytów (1 komputer = 1 audyt) miała by być losowa, ale zawsze powinien istnieć jakiś cel w danym miesiącu np. 5, 10, 15 lub 30szt. (+-5 szt. lub +-10%).
Dodatkowo rozkład tych audytów miałby być nieregularny i w miarę równomiernie rozłożony (ale nie idealnie równomiernie) np. przy 30 audytach nie chciałbym, aby był 1 audyt dziennie lub wszystkie 30.
Celem tego jest przygotowanie takiego harmonogramu, aby audytor i audytowany nie wiedzieli kiedy i jakich rozmiarów będą audyty przy jednoczesnym wykonaniu ich określonej ilości (cel).

[30 audytów w 30 dniowym miesiącu]
Nieprawidłowy |1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1| - (nazbyt równomierny rozkład)
screenshot-20200731165432.png
Nieprawidłowy |30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0| - (brak rozkładu)
screenshot-20200731165506.png
Nieprawidłowy |0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,3,4,5,6,7| - (możliwy do przewidzenia rozkład)
screenshot-20200731170941.png
Prawidłowy |2,0,1,1,2,1,0,1,3,1,0,0,1,1,0,1,2,1,0,1,1,2,1,0,1,3,1,0,1,1| - (nierównomierny, ale też ciężki do przewidzenia rozkład)
screenshot-20200731165234.png
[3 audyty w 29 dniowym miesiącu]
Prawidłowy |0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0|
screenshot-20200731172011.png

Taki rozkład również odpada:
[30 audytów w 30 dniowym miesiącu]
Nieprawidłowy |0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0|
screenshot-20200731172248.png

Proszę o pomoc w utworzeniu algorytmu, który będzie generował harmonogram zgodny z powyższymi założeniami.

2

Skoro ma być układ w miarę losowy, ale nie idealnie po równo, to wytłumaczę jak ja bym to zrobił na przykładzie miseczek z ziarenkami grochu ;)

**1) **stawiasz na stole tyle miseczek, ile jest Ci potrzebne (czyli po miseczce na każdy dzień roboczy, w którym jest możliwość planowania kontroli)
2) określasz, ile chcesz w danym miesiącu przeprowadzić kontroli - tyle ziarenek grochu wyciągasz ze stolika i kładziesz na stole
3) rozkładasz ziarenka po równo do miseczek, uzyskując rozkład zbliżony do tego, który pokazałeś na rysunku pierwszym
4) określasz, jak bardzo chcesz go urozmaicić
**5) **w oparciu o to, co ustaliłeś w pkt. 4, wykonujesz X razy sekwencję polegającą na wylosowaniu miseczki, z które bierzesz ziarenko oraz miseczki, do której je przełożysz
6) jeśli chcesz uniknąć zbyt dużych różnic między miseczkami, możesz w pkt. 5 dodać dodatkowe warunki - np. że jeśli w miseczce, z której wyciągasz jest mniej o Y niż było pierwotnie, to ponawiasz losowanie miseczki źródłowej, albo że jeśli miseczka docelowa ma o Z więcej niż stan startowy, to losujesz inną, do której przełożysz ziarenko.
7) w ramach dodatkowych warunków możesz dodać sprawdzenie, czy któraś miska nie przekroczyła jakiegoś z zadanych parametrów - wartość max, min albo czy została wylosowana więcej niż ileś razy, a jeśli tak, to wypada z dalszych losowań.
8) możesz także uwzględnić dni weekendowe - poprzez nadanie specjalnych warunków dla wybranych miseczek - np. weekend może mieć większą ilość ziarenek niż pozostałe dni, albo nie może zejść poniżej jakiejś wartości, która jest wyższa niż Y.

Operując tymi parametrami, czyli ilością losowań oraz wartościami limitów możesz dość precyzyjnie ustalić zakres wartości/rozrzut, który otrzymasz na końcu działania algorytmu groszkowego ;)

1

To daje w miarę sensowne wyniki dla dużej liczby audytów i dużej liczby dni. Przy małej liczbie audytów ma tendencję do skupiania się na pierwszych dniach, ale to można poprawić wagą przejścia do nowego dnia:

using System;
using System.Threading.Tasks;
					
public class Program
{
	public static void Main()
	{
		int days = 30;
		int audits = 30;
		
		int filled = 0;
		int day = 1;
		Random random = new Random();
		
		int auditsToday = 0;
		while(filled < audits){
			if(random.NextDouble() < 1.0 / 2){
				auditsToday ++;
				filled ++;
			}
			
			if(day < days && random.NextDouble() < 0.5){
				Console.WriteLine($"{auditsToday}");
				day ++;
				auditsToday = 0;
			}
		}
		
		while(day <= days){
			Console.WriteLine($"{auditsToday}");
			day ++;
			auditsToday = 0;
		}
	}
}

Idea: każdego dnia losuję, czy robię audyt z szansą 1/2, a potem losuję z tą samą szansą, czy idę do następnego dnia, czy zostaję tutaj. Prawdopodobieństwa można zmieniać i dowodzić sensowności rozkładu, ale dla prostego przypadku działa okej.

screenshot-20200731184124.png

2

Problem można też zredukować do losowania ze zwracaniem. Dopóki nie mamy wszystkich audytów, dopóty losujemy dzień z rozkładu jednostajnego i dodajemy audyt. To w sumie spełnia chyba wszystkie warunki, nie ma problemów z dużą/małą liczbą dni lub dużą/małą liczbą audytów.

using System;
using System.Threading.Tasks;
using System.Linq;

public class Program
{
    public static void Main()
    {
        int days = 30;
        int audits = 30;

        Random random = new Random();
		int[] auditsPerDay = Enumerable.Range(0, days).Select(i => 0).ToArray();

        int filled = 0;
        while(filled < audits){
            int day = random.Next(0, days - 1);
			auditsPerDay[day]++;
			filled ++;
        }
		
		foreach(var i in auditsPerDay){
			Console.WriteLine(i);
		}
    }
}

screenshot-20200731230332.png

0

A to nie wystarczyłoby użyć rozkładu Poissona z \lambda = \frac{n}{30}?

4

Co Wy wyprawiacie to nie czaje. Z czym Wy macie problem.

Boerzesz laczna oczekiwana liczbe audytow i dzirlisz przez ilosc dni audytow. To jest srednia Teojego rozkladu.
Nastepnir z wybranym odhyleniem standardowym i ewebtualnie wartoscia max i min se losujesz codziennie, pod warunkiem ze suma audytow nie przekroczyla oczekiwanej sumy, a w oststnim dniu juz nie losujesz tylko dobierasz taka liczbe by suma sie zgadzala.

Ewentualnie na kazdy dzoen se aktualizujesz srednia rozkladu = pozostala oczekiwana ilosc fni audytu / pozostsle dni audytu.

2

Mały offtopic: po co robić algorytm na audyt ręczny, skor takie rzeczy sie automatyzuje.

Przykładowo: https://www.eset.com/pl/business/enterprise-inspector/
Wszystkie komputery są monitorowane automatycznie, a dziwne zachowanie procesów jest zgłaszane analitykowi, który dodaje/poprawia reguły co jest dziwnym zachowaniem, co jest zagrożeniem, a co normalne.
Bez wątpienie będzie to skuteczniejsze, niż losowy harmonogram inspekcji maszyn.

0
Julian_ napisał(a):

... a w oststnim dniu juz nie losujesz tylko dobierasz taka liczbe by suma sie zgadzala.

Np minus 10, czyli w ostatnim dniu masz odkręcić 10 audytów zrobionych w dniach poprzednich :D

1
_13th_Dragon napisał(a):
Julian_ napisał(a):

... a w oststnim dniu juz nie losujesz tylko dobierasz taka liczbe by suma sie zgadzala.

Np minus 10, czyli w ostatnim dniu masz odkręcić 10 audytów zrobionych w dniach poprzednich :D

[Julian_ napisał(a)]

se losujesz codziennie, pod warunkiem ze suma audytow nie przekroczyla oczekiwanej sumy

0

Ja wykorzystałem pewien algorytm do generowania danych wejściowych do testowania innego algorytmu.
Miałem do dyspozycji kilkanaście przebiegów zanotowanych wcześniej z realnych pomiarów.

  1. Wyliczam sumaryczny wynik dla całości (w twoim przypadku liczbę audytów)
  2. Dziele okres (w twoim przypadku liczba dni) na pół, dla każdego dostępnego realnego przebiegu notuje ile procent jest po lewej
  3. Jedno z: Wylosowuje jeden z procentów z punktu; 2. Wylosowuje trzy procenty i liczę średnią; 3. Aproksymuje do funkcji i losuję z takim rozkładem.
  4. Z wartości z punktu 2 pobieram procent z punktu 3 i przypisuje do lewej polowy, resztę do prawej.
  5. W pkt 4 dostałem dwa zakresy z przypisanymi wartościami, rekurencyjnie dla obu połówek powtarzam od punktu 2

1 użytkowników online, w tym zalogowanych: 0, gości: 1