Рисование сети

Нам понадобится библиотека Python Imaging Library. Если вы ее еще не установили, обратитесь к приложению А, где приведены инструкции по скачиванию и установке последней версии.

Код рисования сети прямолинеен. Надо создать изображение, нарисовать отрезки между людьми, а потом – узлы, представляющие каждого человека. Имена людей наносятся во вторую очередь, чтобы линии их не перекрывали. Добавьте следующую функцию в файл socialnetwork.py:

def drawnetwork(sol):

#   Создать изображение

img=Image.new(‘RGB’,(400,400),(255,255,255)) draw=ImageDraw.Draw(img)

#   Создать словарь позиций

pos=dict([(people[i],(sol[i*2],sol[i*2+1])) for i in range(0,len(people))])

#   Нарисовать соединительные отрезки for (a,b) in links:

draw.line((pos[a],pos[b]),fill=(255,0,0))

#   Нанести имена людей for n,p in pos.items( ):

draw.text(p,n,(0,0,0))

img.show( )

Для запуска этой функции в интерактивном сеансе перегрузите модуль и вызовите функцию:

>>> reload(socialnetwork) >>> drawnetwork(sol)

На рис. 5.9 показан возможный результат оптимизации. Разумеется, ваше решение будет отличаться от приведенного. Иногда решение выглядит довольно странно. Так как мы ставили себе целью

Рис. 5.9. Размещение, получившееся в результате минимизации количества пересечений

лишь минимизировать количество пересечений, то целевая функция не штрафует за слишком острые углы или за то, что два узла оказались чересчур близко друг к другу. В данном случае алгоритм оптимизации ведет себя как джинн, исполняющий ваши желания буквально, поэтому так важно четко формулировать, чего вы хотите. Зачастую решение удовлетворяет критерию оптимальности, но выглядит совершенно не так, как вы ожидали.

Чтобы штрафовать за слишком близкое расположение узлов, можно вычислить расстояние между узлами и разделить его на желательное минимальное расстояние. Модифицируйте функцию crosscount, добавив в конец (перед return) следующий код:

for i in range(len(people)): for j in range(i+1,len(people)):

#       Получить позиции обоих узлов (x1,y1),(x2,y2)=loc[people[i]],loc[people[]]]

#       Вычислить расстояние между ними dist=math.sqrt(math.pow(x1-x2,2)+math.pow(y1-y2,2))

#       Штраф, если расстояние меньше 50 пикселей if dist<50:

total+=(1.0-(dist/50.0))

Тем самым мы увеличиваем стоимость для каждой пары узлов, расположенных на расстоянии менее 50 пикселей друг от друга, пропорционально расстоянию. Если они оказались в одной и той же точке, то штраф составит 1. Снова выполните оптимизацию и посмотрите, удалось ли растянуть размещение.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100