Diskuse Elektrika.cz

HYBRIDNÍ zóna => Technická podpora výrobce TECO Kolín radí odborníkům => Téma založeno: Crossi 26.08.2013, 21:47



Název: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Crossi 26.08.2013, 21:47
Má někdo zkušenosti s naprogramování m generátoru náhodných čísel v Mosaicu?
Asi se mi budou hodit všechny nápady jaký vás napadnou.


Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Slavomír Skopalík 26.08.2013, 22:04
Pokud to neni opravdu nutne, tak se pouzivaji generatory psedonahodnych cisel. Tj. zvenku se tvari jako nahodne, ale jejich posloupnost je predem dana.
Maji tu vyhodu, ze v pripade chyby v programu, je mozne cely proces otestovat.
Mezi nejjednodusi patri posuvny register + XOR hradlo z nekterych z poslednich bitu.

Kratke pojednani treba zde:
http://www.kemt.fei.tuke.sk/predmety/KEMT414_AK/_materialy/Cvicenia/kryp_4.pdf

http://en.wikipedia.org/wiki/Random_number_generation

Ukazka kodu (netestoval jsem to):

m_w = <choose-initializer>;    /* must not be zero */
m_z = <choose-initializer>;    /* must not be zero */
 
uint get_random()
{
    m_z = 36969 * (m_z & 65535) + (m_z >> 16);
    m_w = 18000 * (m_w & 65535) + (m_w >> 16);
    return (m_z << 16) + m_w;  /* 32-bit result */
}

Zajisteni opravdu nahodneho generatoru je velmi slozite bez specialniho HW.


Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Milan Bydžovský 27.08.2013, 13:13
Pokud stačí psedonáhodné číslo, zde je kód přepsaný z Cčka do ST, který lze v PLC využít. Funkce r4_uniform_01 vrací čísla s rovnoměrným rozdělením. Funkční blok r4_normal_01 vrací čísla s pseudonormální m rozdělením, stejně jako r4_normal, který má navíc parametr pro střední hodnotu a odchylku.

Kód:
FUNCTION r4_uniform_01 : REAL
(*
  R4_UNIFORM_01 returns a unit pseudorandom R4.

  This routine implements the recursion

    seed = 16807 * seed mod ( 2**31 - 1 )
    r4_uniform_01 = seed / ( 2**31 - 1 )

  The integer arithmetic never requires more than 32 bits,
  including a sign bit.

  If the initial seed is 12345, then the first three computations are

    Input     Output      R4_UNIFORM_01
    SEED      SEED

       12345   207482415  0.096616
   207482415  1790989824  0.833995
  1790989824  2035175616  0.947702
*)
  VAR_INPUT
    init_seed : BOOL;
  END_VAR
  VAR
    k : DINT;
  END_VAR
  VAR_IN_OUT
    seed : DINT;
  END_VAR
  VAR_EXTERNAL
    AT %SL52 : DINT;
  END_VAR

  if init_seed then
    seed := %SL52;
  end_if;

  k := seed / 127773;

  seed := 16807 * ( seed - k * 127773 ) - k * 2836;

  IF  seed < 0 THEN
    seed := seed + 2147483647;
  END_IF;
//
//  Although SEED can be represented exactly as a 32 bit integer,
//  it generally cannot be represented exactly as a 32 bit real number!
//
  r4_uniform_01 := DINT_TO_REAL(seed) * 4.656612875E-10;

END_FUNCTION

FUNCTION_BLOCK r4_normal_01
(*
  R4_NORMAL_01 returns a unit pseudonormal R4.

  The standard normal probability distribution function (PDF) has
  mean 0 and standard deviation 1.

  The Box-Muller method is used, which is efficient, but
  generates two values at a time.

*)

  VAR_IN_OUT
    seed : DINT;
  END_VAR
  VAR CONSTANT
    PI : REAL := 3.141592653589793;
  END_VAR
  VAR
    used   : DINT := -1;
    seed2  : DINT;
    y      : REAL;
    r1, r2 : REAL;
  END_VAR
  VAR_OUTPUT
    x : REAL;
  END_VAR

  IF ( used = -1 ) THEN
    used := 0;
  END_IF;
//
//  If we've used an even number of values so far, generate two more, return one,
//  and save one.
//
  IF used MOD 2 = 0 THEN
    r1 := r4_uniform_01 ( false, seed );


    seed2 := seed;
    r2 := r4_uniform_01 ( false, seed2 );

    x := sqrt ( -2.0 * log ( r1 ) ) * cos ( 2.0 * PI * r2 );
    y := sqrt ( -2.0 * log ( r1 ) ) * sin ( 2.0 * PI * r2 );
//
//  Otherwise, return the second, saved, value and the corresponding
//  value of SEED.
//
  ELSE
    x := y;
    seed := seed2;
  END_IF;

  used := used + 1;

END_FUNCTION_BLOCK


FUNCTION_BLOCK r4_normal
(*

  R4_NORMAL returns a scaled pseudonormal R4.

  The normal probability distribution function (PDF) is sampled,
  with mean A and standard deviation B.

*)
  VAR
    i_r4_normal_01 : r4_normal_01;
  END_VAR

  VAR_INPUT
    a : REAL;
    b : REAL;
  END_VAR
  VAR_IN_OUT
    seed : DINT;
  END_VAR
  VAR_OUTPUT
    x : REAL;
  END_VAR

  i_r4_normal_01(seed := seed);
  x := a + b * i_r4_normal_01.x;

END_FUNCTION_BLOCK


Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Crossi 28.08.2013, 00:05
Zatím děkuji za inspiraci pokusím se to použít.


Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Erhard Mareček 04.09.2013, 10:01
Použil jsem tohle:

Random                : UDINT;

Random := MOD(Random*214013 + 2531011, 16777216);     // Random generator

Odzkoušeno.