рдЖрдЬ, рдХрдИ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдореЗрдВ, рддрдВрддреНрд░рд┐рдХрд╛ рдиреЗрдЯрд╡рд░реНрдХ (рдПрдирдПрд╕) рдХрд╛ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдорд╢реАрди рд╕реАрдЦрдиреЗ рдХреЗ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рдкрд░ рдПрдирдПрд╕ рдХрд╛ рдореБрдЦреНрдп рд▓рд╛рдн рдпрд╣ рд╣реИ рдХрд┐ рд╡реЗ рдбреЗрдЯрд╛ рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реНрдкрд╖реНрдЯ рдкреИрдЯрд░реНрди рдирд╣реАрдВ рджрд┐рдЦрд╛рддреЗ рд╣реИрдВред NSs рдХреЗ рдмреАрдЪ рдХреНрд▓рд╛рд╕рд┐рдХ рдкреНрд░рддрд┐рдорд╛рди рддреНрд░реБрдЯрд┐ рдХреЗ рдкрд┐рдЫрдбрд╝реЗ рдкреНрд░рд╕рд╛рд░ рдХреЗ рд╕рд╛рде рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рдиреЗрдЯрд╡рд░реНрдХ рд╣реИред
рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдкрд┐рдЫрдбрд╝реЗ рдкреНрд░рд╕рд╛рд░ рдХреЗ рд╕рд╛рде рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЬреБрдбрд╝реЗ рдПрдирдПрд╕ рдХреЗ рдХрдИ рдлрд╛рдпрджреЗ рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рдореБрдЦ рд╣реИ, рдЬреЛ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЗ рд╡рд░реНрдЧреАрдХрд░рдг рдХреА рдХрд╛рдлреА рдЙрдЪреНрдЪ рд╕рдЯреАрдХрддрд╛ рд╣реИ, рдЬреЛ рдЙрдирдХреЗ рдХрд╛рдордХрд╛рдЬ рдХреЗ "рдордЬрдмреВрдд" рдЧрдгрд┐рддреАрдп рддрдВрддреНрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рд▓реЗрдХрд┐рди, рджреВрд╕рд░реА рдУрд░, рдХрдорд┐рдпрд╛рдВ рднреА рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рд░рд┐рдЯреЗрди рдХрд░рдиреЗ рдХреА рдкреНрд░рд╡реГрддреНрддрд┐, рдЬрдм рдПрдирдПрд╕ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЗ рдирдореВрдиреЗ рдХреА рд╕реНрдерд╛рдиреАрдп рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЕрдкрдиреА рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдХреНрд╖рдорддрд╛ рдЦреЛ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдордирдорд╛рдирд╛ рдбреЗрдЯрд╛ рдкрд░ рд╕реЗрдЯ рдХрд┐рдП рдЧрдП рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЗ рдмрд╛рд╣рд░ рд╡рд░реНрдЧреАрдХрд░рдг рдпрд╛ рдкреВрд░реНрд╡рд╛рдиреБрдорд╛рди рдХреЗ рд╕рд╛рдзрди рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдирдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рджрдХреНрд╖рддрд╛ рдФрд░ рддреЗрдЬреА рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдЖрд▓реЗрдЦ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдПрдХ рддрд╛рд░реНрдХрд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЬреБрдбрд╝реЗ рдмрд╛рдЗрдирд░реА рдПрдирдПрд╕ (рдмрд╛рдЗрдирд░реА рдЪрд░ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд▓рдХреНрд╖реНрдп рдореВрд▓реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ) рдХреЗ рдПрдХ рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЗ рдкреАрдЫреЗ рдкреНрд░рд╕рд╛рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рддрдВрддреНрд░ рдирд╣реАрдВ рд╣реИред рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдЪрд░рдг рдореЗрдВ, рдЬрдм рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдирдореВрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдП рдЧрдП рдХрдИ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдЧрдгрдирд╛рдУрдВ рдХреЗ рдмрдЬрд╛рдп, рдиреНрдпреВрд░реЙрдиреНрд╕ рдХреЗ рд╡рдЬрди рдЧреБрдгрд╛рдВрдХ рдХрд╛ рдЧрдарди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЧреБрдгрд╛рдВрдХ рдХрд╛ рдПрдХ рдПрдХрд▓ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЪрдпрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЗ рд╕рдордп рдХреЛ рдХрд╛рдлреА рдХрдо рдХрд░ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдПрдХ рдФрд░ рдореМрд▓рд┐рдХ рд▓рд╛рдн рдиреЗрдЯрд╡рд░реНрдХ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдЕрднрд╛рд╡ рд╣реИред
рдЕрдВрдЬреАрд░ рдореЗрдВред рдПрдХ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рддрд╛рд░реНрдХрд┐рдХ рддрдВрддреНрд░рд┐рдХрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛ рдмреНрд▓реЙрдХ рдЖрд░реЗрдЦ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдПрдХ рдмрд╛рдЗрдирд░реА рд░реИрдВрдбрдо рдПрдирдПрд╕ рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рд░реВрдк рд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рддреАрди рдкрд░рддреЛрдВ рд╕реЗ рдмрдирд╛ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЗрдирдкреБрдЯ рд╕реЗ рдЖрдЙрдЯрдкреБрдЯ рддрдХ рд╕реВрдЪрдирд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЧрд┐рдирд╛ рдЬрд╛рддрд╛ рд╣реИ:
- : ;
- : ;
- : .
.
, 0 1. , , .
: f(), s=F(x) (0,1), F(x) , . . f()=dF(x)/dx.
, X S, (0,1) . , X, N- , N- , N- , . , , .
, , F(x) Xi (i=1,2,тАж,N) . Fi(x), i- . . , :
, N X. : a тАУ ; x0 тАУ , .
, S . N- , W={w0, w1, w2, w3, тАж, wN} , S={s1, s2, s3, тАж, sN}, , :
, , , . .
- , , W :
N- ,
. ( ), . , .
W , , . N- , : a1, a2, a3, тАж, aN, 0<ai<1. , , :
n1, n2, n3, тАж, nN тАУ , S ( , ); w0 тАУ , 1. , .
, , . . . -, . .
:
M M , , , Sign, () . , .
, , , , . , , , , .
-тАЩ (https://habr.com/ru/post/424517). , , . , ┬л┬╗ ┬л*┬╗. .
C# ( )using System;
using System.Collections.Generic;
using System.Linq;
namespace RndNeuroNet
{
#region
/// <summary>
///
/// </summary>
public class RandomNeuralNetwork
{
private DistributionFunc[] pDistributionDataFuncs;
private RandomDiscrimBase pNeuroLogicDiscrim;
/// <summary>
///
/// </summary>
public RandomNeuralNetwork()
{
}
/// <summary>
///
/// </summary>
/// <param name="pSourceTermsData"></param>
/// <param name="pTargetFeature"></param>
public void CreateNetwork(double[][] pSourceData, bool[] pTargetFeature,
int iFromPos, int iTargetPos, int iWindowSize,
int iAmountLogicDiscrims, int iLogicDiscrimsMaxTrainRestarts = 1,
int iMaxAmountDistributionPoints = 1000, bool bIsNorming = true)
{
//
double[][] pSrcArray = new double[iTargetPos - iFromPos][];
bool[] pDstArray = new bool[iTargetPos - iFromPos];
for (int i = 0, t = iFromPos; t < iTargetPos; t++, i++)
{
//
pSrcArray[i] = (bIsNorming ? NormingE(pSourceData[t], iWindowSize, iWindowSize) : pSourceData[t]);
pDstArray[i] = pTargetFeature[t];
}
//
pDistributionDataFuncs = new DistributionFunc[iWindowSize];
for (int i = 0; i < iWindowSize; i++)
{
//
double[] pTrend2Recalc = pSrcArray.Select(p => p != null ? p[i] : 0).ToArray();
//
pDistributionDataFuncs[i] = new DistributionFunc(pTrend2Recalc, iMaxAmountDistributionPoints);
//
pTrend2Recalc = pDistributionDataFuncs[i].RecalcTrend(pTrend2Recalc);
//
for (int t = 0; t < pSrcArray.Length; t++) pSrcArray[t][i] = pTrend2Recalc[t];
}
//
pNeuroLogicDiscrim = (RandomDiscrimBase)new RandomLogicDiscrim();
pNeuroLogicDiscrim.CreateDiscrim(pSrcArray, pDstArray, 0, pSrcArray.Length,
iWindowSize, iAmountLogicDiscrims, iLogicDiscrimsMaxTrainRestarts);
}
public double CalcResponce(double[] pSourceData, int iWindowSize = 0, bool bIsNorming = true)
{
//
if (iWindowSize <= 0) iWindowSize = pSourceData.Length;
//
pSourceData = (bIsNorming ? NormingE(pSourceData, iWindowSize, iWindowSize) : pSourceData);
//
for (int i = 0; i < iWindowSize; i++)
{
pSourceData[i] = pDistributionDataFuncs[i].RecalcTrend(pSourceData[i]);
}
//
return pNeuroLogicDiscrim.GetPrognos(pSourceData, iWindowSize);
}
/// <summary>
///
/// </summary>
/// <param name="pTrend"></param>
/// <param name="iTargetPosition"></param>
/// <param name="iVectorSize"></param>
/// <returns></returns>
public static double[] NormingE(double[] pTrend, int iTargetPosition,
int iVectorSize, double[] pResultVector = null, bool bIsMinusOffset = false)
{
if (pResultVector == null) pResultVector = new double[iVectorSize];
double dNorming = 0;
for (int i = 0, t = iTargetPosition - iVectorSize; i < iVectorSize; i++, t++)
{
dNorming += pTrend[t];
}
dNorming /= iVectorSize;
double dOffset = (bIsMinusOffset ? 1 : 0);
for (int i = 0, t = iTargetPosition - iVectorSize; i < iVectorSize; i++, t++)
{
pResultVector[i] = (pTrend[t] / dNorming) - dOffset;
}
return pResultVector;
}
}
/// <summary>
///
/// </summary>
public class DistributionFunc
{
private class DataCont
{
public int Counter;
public double SumSrc;
public double ValueP;
}
private readonly SortedDictionary<int, DataCont> pDistribution =
new SortedDictionary<int, DataCont>();
private int m_iMaxAmountDistributionPoints;
private double dAreaMin, dAreaMax;
/// <summary>
///
/// </summary>
public DistributionFunc()
{
}
/// <summary>
///
/// </summary>
public DistributionFunc(double[] pTrend, int iMaxAmountDistributionPoints = 1000)
{
CreateDistribution(pTrend, iMaxAmountDistributionPoints);
}
//
public void CreateDistribution(double[] pTrend, int iMaxAmountDistributionPoints = 1000)
{
m_iMaxAmountDistributionPoints = iMaxAmountDistributionPoints;
dAreaMin = double.MaxValue; dAreaMax = 0;
//
for (int t = 0; t < pTrend.Length; t++)
{
double dTrendVal = pTrend[t];
if (dTrendVal == 0) continue;
dAreaMin = Math.Min(dAreaMin, dTrendVal);
dAreaMax = Math.Max(dAreaMax, dTrendVal);
}
//
for (int t = 0; t < pTrend.Length; t++)
{
double dTrendVal = pTrend[t];
if (dTrendVal == 0) continue;
int iIndex = (int)(((dTrendVal - dAreaMin) / (dAreaMax - dAreaMin)) * m_iMaxAmountDistributionPoints);
DataCont pKeyVal = null;
pDistribution.TryGetValue(iIndex, out pKeyVal);
if (pKeyVal == null) pDistribution.Add(iIndex, pKeyVal = new DataCont());
pKeyVal.Counter++;
pKeyVal.SumSrc += dTrendVal;
}
//
double dSumP = 0;
foreach (KeyValuePair<int, DataCont> dataValue in pDistribution)
{
dataValue.Value.SumSrc /= dataValue.Value.Counter;
dSumP += (double)dataValue.Value.Counter / (double)pTrend.Length;
dataValue.Value.ValueP = dSumP;
}
}
// ,
public double[] RecalcTrend(double[] pTrend, double[] pNewTrend = null)
{
if (pNewTrend == null) pNewTrend = new double[pTrend.Length];
for (int t = 0; t < pTrend.Length; t++)
{
pNewTrend[t] = RecalcTrend(pTrend[t]);
}
return pNewTrend;
}
// ,
public double RecalcTrend(double dTrendVal)
{
int iIndex = (int)(((dTrendVal - dAreaMin) / (dAreaMax - dAreaMin)) * m_iMaxAmountDistributionPoints);
if (iIndex < 0) iIndex = pDistribution.Keys.Min();
if (iIndex > pDistribution.Keys.Max()) iIndex = pDistribution.Keys.Max();
if (pDistribution.Keys.Contains(iIndex))
{
dTrendVal = pDistribution[iIndex].ValueP;
}
else
{
int iDnIndex = pDistribution.Keys.Max<int>(p => p < iIndex ? p : 0);
double dDnVal = pDistribution[iDnIndex].ValueP;
int iUpIndex = pDistribution.Keys.Min<int>(p => p > iIndex ? p : int.MaxValue);
double dUpVal = pDistribution[iUpIndex].ValueP;
dTrendVal = (dUpVal - dDnVal) * ((double)(iIndex - iDnIndex) / (double)(iUpIndex - iDnIndex)) + dDnVal;
}
return dTrendVal;
}
}
/// <summary>
///
/// </summary>
public class RandomDiscrimBase
{
public static int GetTermPoint(double[] pNeuronWeights,
double[] pData, int iDataCortegeLength = 0)
{
double dVal = pNeuronWeights[iDataCortegeLength]; //
for (int i = 0; i < iDataCortegeLength; i++) dVal += (pNeuronWeights[i] * pData[i]);
return Math.Sign(dVal);
}
public static int[] GetTermPoint(IList<double[]> pNeuroSurfaces,
double[] pData, int iDataCortegeLength = 0)
{
if (iDataCortegeLength <= 0) iDataCortegeLength = pData.Length;
int[] pLogicData = new int[pNeuroSurfaces.Count];
for (int n = 0; n < pNeuroSurfaces.Count; n++)
{
pLogicData[n] = GetTermPoint(pNeuroSurfaces[n], pData, iDataCortegeLength);
}
return pLogicData;
}
/// <summary>
///
/// </summary>
public virtual void CreateDiscrim(double[][] pSrcData, bool[] pDstData,
int iFromPos, int iToPos, int iDataCortegeLength, int iAmountLogicDiscrims,
int iLogicDiscrimsMaxTrainRestarts)
{
throw new MissingMethodException(" ");
}
/// <summary>
///
/// -1 +1
/// </summary>
public virtual double GetPrognos(double[] pTermPointData, int iDataCortegeLength = -1)
{
throw new MissingMethodException(" ");
}
}
/// <summary>
///
/// </summary>
public class RandomLogicDiscrim : RandomDiscrimBase
{
private IList<double[]> pLogicDiscrims = null;
public LogicFunc.Quine_McCluskey neuronLogic = null;
/// <summary>
///
/// </summary>
public RandomLogicDiscrim()
{
}
/// <summary>
///
/// </summary>
public override void CreateDiscrim(double[][] pSrcArray, bool[] pTargetData,
int iFromPos, int iToPos, int iDataCortegeLength, int iAmountLogicDiscrims,
int iLogicDiscrimsMaxTrainRestarts)
{
Random RndFabric = new Random(Environment.TickCount);
//
int iMaxCounter = 0;
//
neuronLogic = null;
pLogicDiscrims = new List<double[]>();
do
{
//
// - , iAmountLogicDiscrims,
while (pLogicDiscrims.Count < iAmountLogicDiscrims)
{
double[] pNewSurface = new double[iDataCortegeLength + 1];
for (int i = 0; i < iDataCortegeLength; i++)
{
//
double dNormal = RndFabric.NextDouble() - 0.5;
// , (0...1)
double dPoint = RndFabric.NextDouble();
//
pNewSurface[i] = dNormal;
//
pNewSurface[iDataCortegeLength] -= dNormal * dPoint;
}
pLogicDiscrims.Add(pNewSurface);
}
//
ICollection<byte[]> TermInputUp = new LinkedList<byte[]>();
ICollection<byte[]> TermInputDn = new LinkedList<byte[]>();
for (int t = iFromPos; t < iToPos; t++)
{
byte[] pSrcData = GetTermPoint(pLogicDiscrims, pSrcArray[t], iDataCortegeLength)
.Select(p => (byte)(p > 0 ? 1 : 0)).ToArray();
if (pTargetData[t])
TermInputUp.Add(pSrcData);
else
TermInputDn.Add(pSrcData);
}
//
neuronLogic = new LogicFunc.Quine_McCluskey();
neuronLogic.Start(TermInputUp, TermInputDn);
// , . .
// ,
if ((iMaxCounter + 1) < iLogicDiscrimsMaxTrainRestarts)
{
Dictionary<int, int> TermStars = new Dictionary<int, int>(iAmountLogicDiscrims);
for (int i = 0; i < iAmountLogicDiscrims; i++) TermStars.Add(i, 0);
foreach (byte[] pTerm in neuronLogic.Result.Terms)
{
for (int i = 0; i < iAmountLogicDiscrims; i++)
{
if (pTerm[i] != LogicFunc.LogicFunction.cStarSymb) TermStars[i]++;
}
}
foreach (byte[] pTerm in neuronLogic.ResultNeg.Terms)
{
for (int i = 0; i < iAmountLogicDiscrims; i++)
{
if (pTerm[i] != LogicFunc.LogicFunction.cStarSymb) TermStars[i]++;
}
}
foreach (KeyValuePair<int, int> p in TermStars)
{
// -
if (p.Value <= 0) pLogicDiscrims[p.Key] = null;
}
pLogicDiscrims = pLogicDiscrims.Where(p => p != null).ToList();
}
} while ((pLogicDiscrims.Count < iAmountLogicDiscrims) && (iMaxCounter++ < iLogicDiscrimsMaxTrainRestarts));
}
/// <summary>
///
/// </summary>
/// <param name="pTermPointData"></param>
/// <returns></returns>
public override double GetPrognos(double[] pTermPointData, int iDataCortegeLength = -1)
{
if (iDataCortegeLength <= 0) iDataCortegeLength = pTermPointData.Length;
byte[] pSrcData = GetTermPoint(pLogicDiscrims, pTermPointData, iDataCortegeLength).Select(p => (byte)(p > 0 ? 1 : 0)).ToArray();
int iPrognos = 0;
iPrognos += (neuronLogic.Result.Calculate(pSrcData) ? +1 : -1);
iPrognos += (neuronLogic.ResultNeg.Calculate(pSrcData) ? -1 : +1);
return (iPrognos / 2);
}
}
#endregion
}
namespace LogicFunc
{
#region
/// <summary>
///
/// </summary>
public abstract class LogicFunction
{
// ""
public const byte cStarSymb = 2;
//
public readonly ICollection<byte[]> Terms = new LinkedList<byte[]>();
//
public abstract bool Calculate(bool[] X);
//
public abstract bool Calculate(char[] X);
//
public abstract bool Calculate(byte[] X);
}
/// <summary>
///
/// </summary>
public class Dnf : LogicFunction
{
public static bool Calculate(byte[] X, byte[] term)
{
bool bResult = true;
for (int i = 0; i < term.Length; i++)
{
if ((term[i] == cStarSymb) || (term[i] == X[i])) continue;
bResult = false;
break;
}
return bResult;
}
public override bool Calculate(byte[] X)
{
bool bResult = false;
foreach (byte[] term in Terms)
{
bool bTermVal = true;
for (int i = 0; i < term.Length; i++)
{
if ((term[i] >= cStarSymb) || (term[i] == X[i])) continue;
bTermVal = false;
break;
}
//bResult |= bTermVal;
if (bTermVal)
{
bResult = true;
break;
}
}
return bResult;
}
public override bool Calculate(char[] X)
{
bool bResult = false;
foreach (byte[] term in Terms)
{
bool bTermVal = true;
for (int i = 0; i < term.Length; i++)
{
if ((term[i] >= cStarSymb) || (term[i] == (byte)(X[i] == '0' ? 0 : 1))) continue;
bTermVal = false;
break;
}
//bResult |= bTermVal;
if (bTermVal)
{
bResult = true;
break;
}
}
return bResult;
}
public override bool Calculate(bool[] X)
{
bool bResult = false;
foreach (byte[] term in Terms)
{
bool bTermVal = true;
for (int i = 0; i < term.Length; i++)
{
if ((term[i] >= cStarSymb) || ((term[i] != 0) == X[i])) continue;
bTermVal = false;
break;
}
//bResult |= bTermVal;
if (bTermVal)
{
bResult = true;
break;
}
}
return bResult;
}
}
/// <summary>
///
/// </summary>
public class TreeFuncTerm
{
//
public class TreeNodeEnd { }
//
private readonly TreeNodeEnd pCommonTreeNodeEnd = new TreeNodeEnd();
//
private readonly object[] rootNode = new object[3];
//
private readonly bool IsNewTreeNodeEndMode = false;
// ()
private int _rang = 0;
public int Rang
{
get { return _rang; }
}
//
private int enumerationPos = 0;
private object[][] enumerationBuf;
//,
private byte[] enumerationTerm;
public byte[] EnumerationTerm
{
get { return enumerationTerm; }
}
// ,
private TreeNodeEnd enumerationNode;
public TreeNodeEnd EnumerationNode
{
get { return enumerationNode; }
}
//
private UInt32 _count = 0;
public UInt32 Count
{
get { return _count; }
}
//
public TreeFuncTerm(bool bNewTreeNodeEndMode = false)
{
IsNewTreeNodeEndMode = bNewTreeNodeEndMode;
Clear();
}
//
public void Clear()
{
_count = 0;
_rang = 0;
enumerationPos = 0;
enumerationBuf = null;
enumerationTerm = null;
enumerationNode = null;
rootNode[0] = rootNode[1] = rootNode[2] = null;
}
//
public TreeNodeEnd EnumerationInit()
{
enumerationPos = 0;
enumerationTerm = new byte[_rang];
enumerationTerm[0] = 0;
enumerationNode = null;
enumerationBuf = new object[_rang][];
enumerationBuf[0] = rootNode;
//
return EnumerationNextNode();
}
//
public TreeNodeEnd EnumerationNextNode()
{
int iIsNext = (enumerationNode != null ? 1 : 0);
enumerationNode = null;
while ((enumerationNode == null) && (enumerationPos >= 0))
{
object pNextNode = null;
int iSymb = enumerationTerm[enumerationPos] + iIsNext;
for (object[] pNodes = enumerationBuf[enumerationPos]; iSymb < 3; iSymb++)
{
if ((pNextNode = pNodes[iSymb]) != null) break;
}
if (pNextNode == null)
{
//
enumerationPos--;
iIsNext = 1;
}
else
{
enumerationTerm[enumerationPos] = (byte)iSymb;
if (pNextNode is TreeNodeEnd)
{
//
enumerationNode = (TreeNodeEnd)pNextNode;
}
else
{
//
enumerationPos++;
enumerationBuf[enumerationPos] = (object[])pNextNode;
enumerationTerm[enumerationPos] = 0;
iIsNext = 0;
}
}
}
return enumerationNode;
}
//
public TreeNodeEnd Add(byte[] term)
{
_rang = Math.Max(_rang, term.Length);
object[] pCurrNode = rootNode;
int iTermLength1 = term.Length - 1;
for (int i = 0; i < iTermLength1; i++)
{
byte cSymb = term[i];
object pNextNode = pCurrNode[cSymb];
if (pNextNode == null)
{
pNextNode = new object[3];
pCurrNode[cSymb] = pNextNode;
}
pCurrNode = (object[])pNextNode;
}
object pNewNode = pCurrNode[term[iTermLength1]];
if (pNewNode == null)
{
pNewNode = (IsNewTreeNodeEndMode ? new TreeNodeEnd() : pCommonTreeNodeEnd);
pCurrNode[term[iTermLength1]] = pNewNode;
_count++;
}
return (TreeNodeEnd)pNewNode;
}
//
public TreeNodeEnd Remove(byte[] term)
{
object[] pCurrNode = rootNode;
int iTermLength1 = term.Length - 1;
for (int i = 0; i < iTermLength1; i++)
{
pCurrNode = (object[])pCurrNode[term[i]];
if (pCurrNode == null) break;
}
TreeNodeEnd pRemovedNode = null;
if (pCurrNode != null)
{
//
pRemovedNode = (TreeNodeEnd)pCurrNode[term[iTermLength1]];
if (pRemovedNode != null)
{
//
pCurrNode[term[iTermLength1]] = null;
// -
_count--;
}
}
return pRemovedNode;
}
//
public void Remove(IEnumerable<byte[]> RemovedTerms)
{
if ((RemovedTerms == null) || (RemovedTerms.Count() == 0)) return;
foreach (byte[] x1 in RemovedTerms)
{
//- Remove
// IsContains
Remove(x1);
}
}
//
public bool Contains(byte[] term)
{
object pCurrNode = rootNode;
for (int i = 0; i < term.Length; i++)
{
pCurrNode = ((object[])pCurrNode)[term[i]];
if (pCurrNode == null) break;
}
return ((pCurrNode != null) && (pCurrNode is TreeNodeEnd));
}
// ,
//
public bool IsCalculateTrue(byte[] term)
{
return IsCalculateTrue(rootNode, term, 0);
}
//
private static bool IsCalculateTrue(object[] pCurrNode,
byte[] term, int iStartPos)
{
int iTermLength1 = term.Length - 1;
while ((pCurrNode != null) && (iStartPos < iTermLength1))
{
byte cSymb = term[iStartPos++];
if (cSymb != LogicFunction.cStarSymb)
{
pCurrNode = (object[])pCurrNode[cSymb];
}
else
{
if ((pCurrNode[0] != null) && (pCurrNode[1] != null))
{
if (IsCalculateTrue((object[])pCurrNode[1], term, iStartPos)) return true;
pCurrNode = (object[])pCurrNode[0];
}
else
{
pCurrNode = (object[])(pCurrNode[0] != null ? pCurrNode[0] : pCurrNode[1]);
}
}
}
TreeNodeEnd pEndNode = null;
if (pCurrNode != null)
{
byte cSymb = term[iTermLength1];
if (cSymb != LogicFunction.cStarSymb)
{
pEndNode = (TreeNodeEnd)pCurrNode[cSymb];
}
else
{
pEndNode = (TreeNodeEnd)(pCurrNode[0] != null ? pCurrNode[0] : pCurrNode[1]);
}
}
return (pEndNode != null);
}
// ,
//
public void GetAllCalculateTrueTerms(byte[] term,
ICollection<TreeNodeEnd> pAllCalculateTrueTermsList)
{
pAllCalculateTrueTermsList.Clear();
GetAllCalculateTrueTerms(rootNode, term, 0, pAllCalculateTrueTermsList);
}
//
private static void GetAllCalculateTrueTerms(object[] pCurrNode,
byte[] term, int iStartPos, ICollection<TreeNodeEnd> pAllCalculateTrueTermsList)
{
int iTermLength1 = term.Length - 1;
while ((pCurrNode != null) && (iStartPos < iTermLength1))
{
byte cSymb = term[iStartPos++];
if (cSymb != LogicFunction.cStarSymb)
{
pCurrNode = (object[])pCurrNode[cSymb];
}
else
{
if ((pCurrNode[0] != null) && (pCurrNode[1] != null))
{
GetAllCalculateTrueTerms((object[])pCurrNode[1], term, iStartPos,
pAllCalculateTrueTermsList);
pCurrNode = (object[])pCurrNode[0];
}
else
{
pCurrNode = (object[])(pCurrNode[0] != null ? pCurrNode[0] : pCurrNode[1]);
}
}
}
if (pCurrNode != null)
{
byte cSymb = term[iTermLength1];
if (cSymb != LogicFunction.cStarSymb)
{
TreeNodeEnd pEndNode = (TreeNodeEnd)pCurrNode[cSymb];
if (pEndNode != null) pAllCalculateTrueTermsList.Add(pEndNode);
}
else
{
if (pCurrNode[0] != null) pAllCalculateTrueTermsList.Add((TreeNodeEnd)pCurrNode[0]);
if (pCurrNode[1] != null) pAllCalculateTrueTermsList.Add((TreeNodeEnd)pCurrNode[1]);
}
}
}
}
/// <summary>
/// ----
/// </summary>
public class Quine_McCluskey
{
//
private readonly Dnf _result = new Dnf();
public Dnf Result
{
get { return _result; }
}
//
private readonly Dnf _resultNeg = new Dnf();
public Dnf ResultNeg
{
get { return _resultNeg; }
}
//
private static void Skleivanie(TreeFuncTerm X1Tree,
TreeFuncTerm X2Tree, TreeFuncTerm NegativTree,
TreeFuncTerm InpNegTerms, TreeFuncTerm AllOutTerms)
{
bool IsVirtSkleivOn = ((NegativTree != null) &&
(InpNegTerms != null) && (InpNegTerms.Count != 0));
for (TreeFuncTerm.TreeNodeEnd x1 = X1Tree.EnumerationInit();
x1 != null; x1 = X1Tree.EnumerationNextNode())
{
bool bIsSkleiv = false;
byte[] pCurrTerm = X1Tree.EnumerationTerm;
for (int iPos = 0; iPos < pCurrTerm.Length; iPos++)
{
byte cSymbSav = pCurrTerm[iPos];
if (cSymbSav == LogicFunction.cStarSymb) continue;
//
pCurrTerm[iPos] = (byte)(1 - cSymbSav);
if (X1Tree.Contains(pCurrTerm))
{
bIsSkleiv = true;
if (cSymbSav == 0)
{
pCurrTerm[iPos] = LogicFunction.cStarSymb; //
X2Tree.Add(pCurrTerm);
}
}
// , NegativTree
else if (IsVirtSkleivOn && !NegativTree.Contains(pCurrTerm))
{
pCurrTerm[iPos] = LogicFunction.cStarSymb; //
if (!InpNegTerms.IsCalculateTrue(pCurrTerm))
{
bIsSkleiv = true;
X2Tree.Add(pCurrTerm);
}
}
pCurrTerm[iPos] = cSymbSav;
}
// ,
if (!bIsSkleiv && (AllOutTerms != null)) AllOutTerms.Add(pCurrTerm);
}
}
//
//
private static void DeleteDublicatingTerms(
IEnumerable<byte[]> InX1, TreeFuncTerm OutX2Tree)
{
OutX2Tree.Clear();
foreach (byte[] x1 in InX1) OutX2Tree.Add(x1);
}
// .
// , , (),
// тАЬ тАУ тАЭ
// (http://www.studfiles.ru/preview/5175815/page:4/)
private static void ReduceRedundancyTerms(TreeFuncTerm AllOutputTerms,
TreeFuncTerm AllInputTerms, ICollection<byte[]> ResultTerms)
{
//
ResultTerms.Clear();
// ,
Dictionary<byte[], HashSet<TreeFuncTerm.TreeNodeEnd>> Outputs2Inputs =
new Dictionary<byte[], HashSet<TreeFuncTerm.TreeNodeEnd>>();
// ,
Dictionary<TreeFuncTerm.TreeNodeEnd, HashSet<byte[]>> Inputs2Outputs =
new Dictionary<TreeFuncTerm.TreeNodeEnd, HashSet<byte[]>>();
//
for (TreeFuncTerm.TreeNodeEnd pNode = AllOutputTerms.EnumerationInit();
pNode != null; pNode = AllOutputTerms.EnumerationNextNode())
{
byte[] outTerm = (byte[])AllOutputTerms.EnumerationTerm.Clone();
// , term
HashSet<TreeFuncTerm.TreeNodeEnd> InpTermsLst = new HashSet<TreeFuncTerm.TreeNodeEnd>();
AllInputTerms.GetAllCalculateTrueTerms(outTerm, InpTermsLst);
Outputs2Inputs.Add(outTerm, InpTermsLst);
foreach (TreeFuncTerm.TreeNodeEnd inputTerm in InpTermsLst)
{
if (!Inputs2Outputs.ContainsKey(inputTerm)) Inputs2Outputs.Add(inputTerm, new HashSet<byte[]>());
Inputs2Outputs[inputTerm].Add(outTerm);
}
}
// -
Inputs2Outputs = Inputs2Outputs.OrderBy(p => p.Value.Count).ToDictionary(p => p.Key, v => v.Value);
// , -
while (Inputs2Outputs.Count > 0)
{
byte[] outTerm = Inputs2Outputs.First().Value.OrderByDescending(q => Outputs2Inputs[q].Count()).First();
ResultTerms.Add(outTerm);
foreach (TreeFuncTerm.TreeNodeEnd inTerm in Outputs2Inputs[outTerm].ToArray())
{
foreach (byte[] outTerm2Del in Inputs2Outputs[inTerm]) Outputs2Inputs[outTerm2Del].Remove(inTerm);
Inputs2Outputs.Remove(inTerm);
}
}
}
//
public static void LogicFuncMinimize(
IEnumerable<byte[]> PositivTerms, ICollection<byte[]> OutPos,
IEnumerable<byte[]> NegativTerms, ICollection<byte[]> OutNeg)
{
TreeFuncTerm InpPosTerms = new TreeFuncTerm(true);
DeleteDublicatingTerms(PositivTerms, InpPosTerms);
int iTotalLevels = InpPosTerms.Rang;
if (iTotalLevels <= 0) return;
TreeFuncTerm OutPosTerms = new TreeFuncTerm();
TreeFuncTerm OutNegTerms = null;
TreeFuncTerm InpNegTerms = null;
if ((NegativTerms != null) && (NegativTerms.Count() != 0))
{
InpNegTerms = new TreeFuncTerm(true);
DeleteDublicatingTerms(NegativTerms, InpNegTerms);
OutNegTerms = new TreeFuncTerm();
//
for (TreeFuncTerm.TreeNodeEnd pNode = InpPosTerms.EnumerationInit();
pNode != null; pNode = InpPosTerms.EnumerationNextNode())
{
if (!InpNegTerms.Contains(InpPosTerms.EnumerationTerm)) continue;
// - X1 NegativTerms
int iPos_Count = PositivTerms.Count(p => Enumerable.SequenceEqual(p, InpPosTerms.EnumerationTerm));
int iNeg_Count = NegativTerms.Count(p => Enumerable.SequenceEqual(p, InpPosTerms.EnumerationTerm));
if (iPos_Count > iNeg_Count)
{
InpNegTerms.Remove(InpPosTerms.EnumerationTerm);
}
else if (iPos_Count < iNeg_Count)
{
InpPosTerms.Remove(InpPosTerms.EnumerationTerm);
}
else //if (iX1_Count == iNeg_Count)
{
InpPosTerms.Remove(InpPosTerms.EnumerationTerm);
InpNegTerms.Remove(InpPosTerms.EnumerationTerm);
}
}
}
//
TreeFuncTerm X1PositivTree = InpPosTerms;
TreeFuncTerm X1NegativTree = InpNegTerms;
int iLevelCounter = 0;
//
while ((X1PositivTree.Count != 0) && (iLevelCounter < iTotalLevels))
{
TreeFuncTerm X2PositivTree = new TreeFuncTerm();
Skleivanie(X1PositivTree, X2PositivTree, X1NegativTree, InpNegTerms, OutPosTerms);
if ((X1NegativTree != null) && (X1NegativTree.Count != 0))
{
TreeFuncTerm X2NegativTree = new TreeFuncTerm();
Skleivanie(X1NegativTree, X2NegativTree, X1PositivTree, InpPosTerms, OutNegTerms);
//
if (iLevelCounter > 0) X1NegativTree.Clear();
X1NegativTree = X2NegativTree;
}
//
if (iLevelCounter > 0) X1PositivTree.Clear();
X1PositivTree = X2PositivTree;
iLevelCounter++;
GC.Collect();
}
if (OutPosTerms.Count > 0)
{
// , cStarSymb
OutPosTerms.Remove(Enumerable.Repeat(LogicFunction.cStarSymb, iTotalLevels).ToArray());
}
//
ReduceRedundancyTerms(OutPosTerms, InpPosTerms, OutPos);
if ((OutNeg != null) && (OutNegTerms != null))
{
if (OutNegTerms.Count > 0)
{
// , cStarSymb
OutNegTerms.Remove(Enumerable.Repeat(LogicFunction.cStarSymb, iTotalLevels).ToArray());
}
//
ReduceRedundancyTerms(OutNegTerms, InpNegTerms, OutNeg);
}
}
//
public void Start(IEnumerable<byte[]> TermsInput)
{
LogicFuncMinimize(TermsInput, _result.Terms, null, null);
}
//
public void Start(IEnumerable<byte[]> TermsInput, IEnumerable<byte[]> NegativTerms)
{
LogicFuncMinimize(TermsInput, _result.Terms, NegativTerms, _resultNeg.Terms);
}
//
public void Start(IEnumerable<char[]> TermsInput)
{
Start(TermsInput.Select(t => t.Select(p => (byte)(p == '0' ? 0 : 1)).ToArray()));
}
//
public void Start(IEnumerable<char[]> TermsInput, IEnumerable<char[]> NegativTerms)
{
Start(TermsInput.Select(t => t.Select(p => (byte)(p == '0' ? 0 : 1)).ToArray()),
NegativTerms.Select(t => t.Select(p => (byte)(p == '0' ? 0 : 1)).ToArray()));
}
//
public void Start(IEnumerable<bool[]> TermsInput)
{
Start(TermsInput.Select(t => t.Select(p => (byte)(p ? 1 : 0)).ToArray()));
}
//
public void Start(IEnumerable<bool[]> TermsInput, IEnumerable<bool[]> NegativTerms)
{
Start(TermsInput.Select(t => t.Select(p => (byte)(p ? 1 : 0)).ToArray()),
NegativTerms.Select(t => t.Select(p => (byte)(p ? 1 : 0)).ToArray()));
}
}
#endregion
}
- , . , , . t N X(t-j) (j=1,2,тАж,N), Sign(X(t)-X(t-1)). , . , . . , . , Sign(X(t)-X(t-1)) . , , - , . . - .
C# ( ) public static void TestRandomNeuralNetwork()
{
//:
const int iTrendSize = 2000;
//:
const int iTestTrendSize = 1000;
//:
const int iWindowSize = 10;
//
const int iOmega = 100;
//-
const int iHarmonics = 5;
//
const int iMinAmpl = 50;
//
const int iMaxAmpl = 100;
// /
const double dNoise2SignalRatio = 0;
//:
const int iAmountLogicDiscrims = 20;
//: -
const int iMaxAmountDistributionPoints = 1000;
//: -
const int iLogicDiscrimsMaxTrainRestarts = 1;
//
int iPrepTrendLength = iTrendSize - iTestTrendSize;
double[] pTrend = new double[iTrendSize];
// -
//for (int t = 0; t < iTrendSize; t++) pTrend[t] = Math.Sin((t * Math.PI) / iOmega) + 200;
//
int[] pFreq = new int[iHarmonics];
int[] pPhase = new int[iHarmonics];
double[] pAmpl = new double[iHarmonics];
// .
Random RndFabric = new Random(Environment.TickCount);
for (int h = 0; h < iHarmonics; h++)
{
pFreq[h] = RndFabric.Next(iOmega/*iPrepTrendLength*/) + 1;
pPhase[h] = RndFabric.Next(iPrepTrendLength);
pAmpl[h] = RndFabric.NextDouble();
}
double iMinValue = double.MaxValue, iMaxValue = 0;
for (int t = 0; t < iTrendSize; t++)
{
double dValue = 0; //iMinAmpl + ((iMaxAmpl - iMinAmpl) * RndFabric.NextDouble());
for (int h = 0; h < iHarmonics; h++)
{
dValue += ((pAmpl[h] * (iMaxAmpl - iMinAmpl)) + iMinAmpl) * Math.Sin(((t + pPhase[h]) * Math.PI) / pFreq[h]);
}
pTrend[t] = dValue;
iMinValue = Math.Min(iMinValue, dValue);
iMaxValue = Math.Max(iMaxValue, dValue);
}
//
if (dNoise2SignalRatio > 0)
{
double dNoiseAmp = (iMaxValue - iMinValue) * dNoise2SignalRatio;
for (int t = 0; t < iTrendSize; t++)
{
pTrend[t] += dNoiseAmp * 2.0 * (RndFabric.NextDouble() - 0.5);
iMinValue = Math.Min(iMinValue, pTrend[t]);
}
}
// ,
if (iMinValue < 0)
{
for (int t = 0; t < iTrendSize; t++) pTrend[t] -= iMinValue;
}
//
double[][] pSourceTrendData = new double[iTrendSize][];
bool[] pTargetFeature = new bool[iTrendSize];
//
for (int t = iWindowSize; t < iTrendSize; t++)
{
//
double[] pNormData = new double[iWindowSize];
for (int i = 0; i < iWindowSize; i++) pNormData[i] = pTrend[t - iWindowSize + i];
pSourceTrendData[t] = pNormData;
//
pTargetFeature[t] = (pTrend[t] >= pTrend[t - 1]);
}
DateTime dtStartDt = DateTime.Now;
RndNeuroNet.RandomNeuralNetwork randomNeuralNetwork = new RndNeuroNet.RandomNeuralNetwork();
randomNeuralNetwork.CreateNetwork(pSourceTrendData, pTargetFeature, iWindowSize, iPrepTrendLength, iWindowSize, iAmountLogicDiscrims,
//iClustersAmount, iClustersRestart,
iLogicDiscrimsMaxTrainRestarts, iMaxAmountDistributionPoints);
//
TimeSpan tsTime = (DateTime.Now - dtStartDt);
//
int iUpGapCounterTrain = 0, iDnGapCounterTrain = 0, iSuccessCounterTrain = 0, iErrorCounterTrain = 0, iIgnoreCounterTrain = 0;
for (int t = iWindowSize; t < iPrepTrendLength; t++)
{
double dPrognos = randomNeuralNetwork.CalcResponce(pSourceTrendData[t]);
if (dPrognos == 0)
{
iIgnoreCounterTrain++;
}
else
{
if (((pTargetFeature[t] ? +1 : -1) * dPrognos) > 0)
{
iSuccessCounterTrain++;
}
else
{
iErrorCounterTrain++;
}
}
// GAP-
if (pTargetFeature[t])
{
iUpGapCounterTrain++;
}
else
{
iDnGapCounterTrain++;
}
}
//
int iUpGapCounterTest = 0, iDnGapCounterTest = 0, iSuccessCounterTest = 0, iErrorCounterTest = 0, iIgnoreCounterTest = 0;
for (int t = iPrepTrendLength; t < iTrendSize; t++)
{
double dPrognos = randomNeuralNetwork.CalcResponce(pSourceTrendData[t]);
if (dPrognos == 0)
{
iIgnoreCounterTest++;
}
else
{
if (((pTargetFeature[t] ? +1 : -1) * dPrognos) > 0)
{
iSuccessCounterTest++;
}
else
{
iErrorCounterTest++;
}
}
// GAP-
if (pTargetFeature[t])
{
iUpGapCounterTest++;
}
else
{
iDnGapCounterTest++;
}
}
//
Console.WriteLine("- = " + iUpGapCounterTrain + Environment.NewLine +
"- = " + iDnGapCounterTrain + Environment.NewLine +
"- = " + iSuccessCounterTrain + Environment.NewLine +
"- = " + iErrorCounterTrain + Environment.NewLine +
"- = " + iIgnoreCounterTrain + Environment.NewLine +
"- = " + iUpGapCounterTest + Environment.NewLine +
"- = " + iDnGapCounterTest + Environment.NewLine +
"- = " + iSuccessCounterTest + Environment.NewLine +
"- = " + iErrorCounterTest + Environment.NewLine +
"- = " + iIgnoreCounterTest + Environment.NewLine +
" = " + (int)tsTime.TotalMinutes + " . " + tsTime.Seconds + " ."
);
Console.WriteLine("Press Enter to exit ...");
Console.ReadLine();
}
, , . , , :
рдПрдирдПрд╕ рдХреА рдХрдореА рдХреЗ рд░реВрдк рдореЗрдВ, рдЙрдкрд▓рдмреНрдз рд░реИрдо рдХреА рдорд╛рддреНрд░рд╛ рдФрд░ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдореЗрдВ рдмрд┐рддрд╛рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдордп рдкрд░ рдЗрд╕рдХреА рдорд╣рд╛рди рдорд╛рдВрдЧреЛрдВ рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдЙрдирдХрд╛ рдореБрдЦреНрдп рдЙрдкрднреЛрдХреНрддрд╛ Quine-Mac'Klaski рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рддрд╛рд░реНрдХрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд╣реИ, рдЕрд░реНрдерд╛рдд, рддреАрд╕рд░реА рдЖрдЙрдЯрдкреБрдЯ рдкрд░рддред рд▓реЗрдХрд┐рди рдХрдИ рддрд╛рд░реНрдХрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреИрд╕реНрдХреЗрдбрд┐рдВрдЧ рдХрд░рдХреЗ рдЗрд╕ рдХрдореА рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИред рдмрд╛рдХреА рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдПрдирдПрд╕ рдиреЗ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдбреЗрдЯрд╛ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдФрд░ рд╡рд░реНрдЧреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЦреБрдж рдХреЛ рдПрдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдЙрдкрдХрд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рд╣реИред