Valentýnská akce je tady! Získej až 80 % extra kreditů ZDARMA na náš interaktivní e-learning. ZJISTIT VÍCE:
NOVINKA: Staň se datovým analytikem a získej jistotu práce, lepší plat a nové kariérní možnosti. Více informací:

Lopatky v1

Optimalizace lopatkoveho kola

Imports System
Imports System.Collections.Concurrent
Imports LopatkyVb

Module Program

  Private Const MaxPocetIteraci As Integer = 10000

  Sub Main(args As String())

    Optimalizovat(500.0, 480.0, 490.0, 475.0, 492.0, 510.0, 505.0, 520.0, 470.0)

    Optimalizovat(10300.0, 10300.0, 10210.0, 10160.0, 10130.0, 10130.0, 10120.0, 10120.0, 10100.0, 10100.0, 10090.0, 10090.0, 10080.0, 10070.0, 10050.0, 10050.0, 10030.0, 10020.0)

    Console.WriteLine()
    Console.WriteLine("Neco zmacknout pro ukonceni")
    Console.ReadKey()
  End Sub

  Private Sub Optimalizovat(ParamArray hmotnosti As Double())
    Dim pocatecniKolo = New Kolo(hmotnosti)

    Dim iterace = 1
    Dim kolo = pocatecniKolo
    While iterace < MaxPocetIteraci AndAlso Iterovat(kolo)
      iterace += 1
    End While

    Console.WriteLine("Vstupni kolo:")
    VypsatKolo(pocatecniKolo)
    Console.WriteLine()

    Console.WriteLine("Vysledne kolo:")
    VypsatKolo(kolo)
    Console.WriteLine()

    Console.WriteLine("Pocet iteraci: {0:N0}", iterace)

    Console.WriteLine()
    Console.WriteLine("******")
    Console.WriteLine()
  End Sub

  Private Sub VypsatKolo(kolo As Kolo)
    Console.WriteLine("Vzdalenost teziste od pocatku: {0:N6}", Math.Sqrt(kolo.Teziste.VzdalenostOdPocatkuKvadrat))
    Console.WriteLine(String.Join("; ", From l In kolo Select String.Format("{0:N1}", l.Hmotnost)))
  End Sub

  ''' <summary>
  ''' Vrati true, pokud doslo k prohozeni
  ''' </summary>
  ''' <param name="kolo">Pouzije se zaroven jako vstupni hodnota pro kolo, ktere se ma optimalizovat, tak jako vystupni hodnota pro vysledne kolo.</param>
  Function Iterovat(ByRef kolo As Kolo) As Boolean
    Dim pocatecni = kolo
    Dim dosloKProhozeni = False
    For a = 0 To pocatecni.Count - 1
      For b = a + 1 To pocatecni.Count - 1
        Dim navrh = pocatecni.ProhoditLopatky(a, b)
        If navrh.Teziste.VzdalenostOdPocatkuKvadrat < kolo.Teziste.VzdalenostOdPocatkuKvadrat Then
          kolo = navrh
          dosloKProhozeni = True
        End If
      Next
    Next
    Return dosloKProhozeni
  End Function

End Module


Class Kolo
  Implements IReadOnlyList(Of Lopatka)

  Private ReadOnly Lopatky As IReadOnlyList(Of Lopatka)

  ''' <summary>
  ''' Nenulove cislo
  ''' </summary>
  ''' <returns></returns>
  Public ReadOnly Property Hmotnost As Double

  Public ReadOnly Property Teziste As Vektor

  Public Sub New(ParamArray hmotnosti As Double())
    If hmotnosti Is Nothing Then Throw New ArgumentNullException(NameOf(hmotnosti))
    Me.Hmotnost = hmotnosti.Sum()
    If Me.Hmotnost = 0.0 Then Throw New ArgumentException("Soucet hmotnosti nesmi byt nula.", NameOf(hmotnosti))
    Dim polohy = Caches.PolohyLopatek.GetValue(hmotnosti.Length)
    Me.Lopatky = New List(Of Lopatka)(hmotnosti.Zip(polohy, AddressOf Lopatka.Create))
    Me.Teziste = Me.SpocitatTeziste()
  End Sub

  Private Function SpocitatTeziste() As Vektor
    Dim result = Vektor.Origin
    For Each lopatka In Me.Lopatky
      result += lopatka.Hmotnost * lopatka.Teziste
    Next
    Return (1.0 / Me.Hmotnost) * result
  End Function

  ''' <summary>
  ''' Vytvori nove kolo s prohozenyma lopatkama na pozicich <paramref name="a"/> a <paramref name="b"/> (pocitano on nuly).
  ''' </summary>
  ''' <param name="a">index lopatky</param>
  ''' <param name="b">index druhe lopatky</param>
  Public Function ProhoditLopatky(a As Integer, b As Integer) As Kolo
    Dim h(Me.Lopatky.Count - 1) As Double
    For i = 0 To h.Length - 1
      Dim j = i
      If i = a Then
        j = b
      ElseIf i = b Then
        j = a
      End If
      h(i) = Me.Lopatky(j).Hmotnost
    Next
    Return New Kolo(h)
  End Function

#Region "Implemetace IReadOnlyList"

  Default Public ReadOnly Property Item(index As Integer) As Lopatka Implements IReadOnlyList(Of Lopatka).Item
    Get
      Return Lopatky(index)
    End Get
  End Property

  Public ReadOnly Property Count As Integer Implements IReadOnlyCollection(Of Lopatka).Count
    Get
      Return Lopatky.Count
    End Get
  End Property

  Public Function GetEnumerator() As IEnumerator(Of Lopatka) Implements IEnumerable(Of Lopatka).GetEnumerator
    Return Lopatky.GetEnumerator()
  End Function

  Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
    Return Lopatky.GetEnumerator()
  End Function

#End Region

End Class

Class Lopatka

  Private Sub New(hmotnost As Double, poloha As Double, teziste As Vektor)
    If teziste Is Nothing Then
      Throw New ArgumentNullException(NameOf(teziste))
    End If

    Me.Hmotnost = hmotnost
    Me.Poloha = poloha
    Me.Teziste = teziste
  End Sub

  Public ReadOnly Property Hmotnost As Double

  ''' <summary>
  ''' Uhel v radianech
  ''' </summary>
  Public ReadOnly Property Poloha As Double

  Public ReadOnly Property Teziste As Vektor

  Public Shared Function Create(hmotnost As Double, poloha As Double) As Lopatka
    Return New Lopatka(hmotnost, poloha, Caches.TezisteLopatek.GetValue(poloha))
  End Function

End Class

Class Vektor

  Public Shared ReadOnly Property Origin As New Vektor(0.0, 0.0)

  Public ReadOnly Property X As Double

  Public ReadOnly Property Y As Double

  Private ReadOnly _VzdalenostOdPocatkuKvadrat As Lazy(Of Double)

  Public ReadOnly Property VzdalenostOdPocatkuKvadrat As Double
    Get
      Return Me._VzdalenostOdPocatkuKvadrat.Value
    End Get
  End Property

  Public Sub New(x As Double, y As Double)
    Me.X = x
    Me.Y = y
    Me._VzdalenostOdPocatkuKvadrat = New Lazy(Of Double)(AddressOf SpocitatVzdalenostOdPocatkuKvadrat)
  End Sub

  Private Function SpocitatVzdalenostOdPocatkuKvadrat() As Double
    Return Me.X * Me.X + Me.Y * Me.Y
  End Function

  Public Overrides Function ToString() As String
    Return $"[{X:N3}, {Y:N3}]"
  End Function

  Public Shared Operator *(left As Double, right As Vektor) As Vektor
    Return New Vektor(left * right.X, left * right.Y)
  End Operator

  Public Shared Operator +(left As Vektor, right As Vektor) As Vektor
    Return New Vektor(left.X + right.X, left.Y + right.Y)
  End Operator

End Class

Module Caches

  ''' <summary>
  ''' Vrati teziste pro polohy / uhly lopatek.
  ''' </summary>
  Public ReadOnly Property TezisteLopatek As New Cache(Of Double, Vektor)(AddressOf TezisteLopatky)

  Private Function TezisteLopatky(ByVal uhel As Double) As Vektor
    Return New Vektor(Math.Cos(uhel), Math.Sin(uhel))
  End Function

  ''' <summary>
  ''' Pro kazdy pocet lopatek vrati rozlozeni uhlu
  ''' </summary>
  Public ReadOnly Property PolohyLopatek As New Cache(Of Integer, IReadOnlyList(Of Double))(AddressOf GetPolohy)

  Private Function GetPolohy(ByVal n As Integer) As IReadOnlyList(Of Double)
    Return New List(Of Double)(From i In Enumerable.Range(1, n) Select 2.0 * Math.PI * i / n)
  End Function

End Module

Class Cache(Of TKey, TValue)

  Private ReadOnly Items As New System.Collections.Concurrent.ConcurrentDictionary(Of TKey, TValue)()

  Private ReadOnly GenerateValue As Func(Of TKey, TValue)

  Public Sub New(generateValue As Func(Of TKey, TValue))
    Me.GenerateValue = generateValue
  End Sub

  Public Function GetValue(key As TKey) As TValue
    Dim result As TValue
    If Not Me.Items.TryGetValue(key, result) Then
      result = GenerateValue(key)
      Me.Items.TryAdd(key, result)
    End If
    Return result
  End Function

End Class

Neformátovaný

Přidáno: 20.9.2019
Expirace: Neuvedeno

Avatar
Autor: Bugmaster
Aktivity