* @author Dennis Eichhorn * @copyright 2013 Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 * @link http://orange-management.com */ namespace phpOMS\Math\Optimization\TSP; /** * Tour class. * * @category Framework * @package phpOMS\DataStorage\Database * @author OMS Development Team * @author Dennis Eichhorn * @license OMS License 1.0 * @link http://orange-management.com * @since 1.0.0 */ class Tour implements \Countable { /** * Cities * * @var City[] * @since 1.0.0 */ private $cities = []; /** * Tour fitness * * @var City[] * @since 1.0.0 */ private $fitness = 0.0; /** * Tour distance * * @var City[] * @since 1.0.0 */ private $distance = 0.0; /** * City pool * * @var CityPool * @since 1.0.0 */ private $cityPool = null; /** * Constructor. * * @param CityPool $pool City pool * @param bool $initialize Initialize with random tours * * @since 1.0.0 * @author Dennis Eichhorn */ public function __construct(CityPool $pool, bool $initialize = false) { $this->cityPool = $pool; if ($initialize) { $this->cities = $this->cityPool->getCities(); shuffle($this->cities); } } /** * Get city. * * @param int $index Index * * @return null|City * * @since 1.0.0 * @author Dennis Eichhorn */ public function getCity($index) { return array_values($this->cities)[$index] ?? null; } /** * Get fitness. * * @return float * * @since 1.0.0 * @author Dennis Eichhorn */ public function getFitness() : float { if ($this->fitness === 0.0 && ($distance = $this->getDistance()) !== 0.0) { $this->fitness = 1 / $distance; } return $this->fitness; } /** * Get tour distance * * @return float * * @since 1.0.0 * @author Dennis Eichhorn */ public function getDistance() : float { if ($this->distance === 0.0) { $distance = 0.0; $count = count($this->cities); for ($i = 0; $i < $count; $i++) { $dest = ($i + 1 < $count) ? $this->cities[$i + 1] : $this->cities[0]; $distance += $this->cities[$i]->getDistanceTo($dest); } $this->distance = $distance; } return $this->distance; } /** * Add city to tour. * * @param City $city City * * @since 1.0.0 * @author Dennis Eichhorn */ public function addCity(City $city) { $this->cities[] = $city; $this->fitness = 0.0; $this->distance = 0.0; } /** * Set city * * @param int $index Index to set/replace * @param City $city City * * @since 1.0.0 * @author Dennis Eichhorn */ public function setCity(int $index, City $city) /* : void */ { $this->cities[$index] = $city; asort($this->cities); $this->fitness = 0.0; $this->distance = 0.0; } /** * Has city. * * @param City $city City * * @return bool * * @since 1.0.0 * @author Dennis Eichhorn */ public function hasCity(City $city) : bool { foreach ($this->cities as $c) { if ($c->equals($city)) { return true; } } return false; } /** * Get city count * * @return int * * @since 1.0.0 * @author Dennis Eichhorn */ public function count() : int { return count($this->cities); } }