displaycontroller.cpp
1 /********************************************************************************
2  * FARSA Experiments Library *
3  * Copyright (C) 2007-2012 *
4  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
5  * Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it> *
6  * Gianluca Massera <emmegian@yahoo.it> *
7  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the Free Software *
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
22  ********************************************************************************/
23 
24 #include "displaycontroller.h"
25 
26 #include <QtGui> // Widget
27 #include <QKeyEvent> // Dialog
28 #include <QFileDialog> // Dialog
29 #include <QMessageBox> // Dialog
30 #include <QImage> // the background image of the controller
31 #include <QComboBox>
32 #include "logger.h"
33 
34 // All the suff below is to avoid warnings on Windows about the use of unsafe
35 // functions. This should be only a temporary workaround, the solution is stop
36 // using C string and file functions...
37 #if defined(_MSC_VER)
38  #pragma warning(push)
39  #pragma warning(disable:4996)
40 #endif
41 
42 #define MAXFREEP 10000
43 
44 namespace farsa {
45 
46 NetworkDialog::NetworkDialog(Evonet* net, QWidget* parent, Qt::WindowFlags flags) : QWidget( parent, flags )
47 {
48  this->enet=net;
49 
50  cneuronn=0; // n. of selected cneurons
51  cscalex=1.0; // x scale for the controller rendering
52  cscaley=1.0; // y scale for the controller rendering
53  pseudomode=0; // the display modality (0=label 1=delta, 2=weight, 3=biases, 4=gain)
54  enet->nselected=0; // number of currently extracted parameters
55  grid=0; // no grid
56 
57  // Creating the main layout. Direction is BottomToTop so that m_layout (added first)
58  // is at bottom, while the toolbar (added last) is on top
59  m_mainLayout = new QVBoxLayout(this);
60  //m_mainLayout->setContentsMargins(0, 0, 0, 0);
61 
62  createActions();
63  // Creating toolbar and adding it to the main layout
64  m_toolBar = new QToolBar(this);
65  m_mainLayout->addWidget(m_toolBar);
66  createToolBars();
67 
68  this->enet->neuronlesions = 0;
69 
70  freep=enet->freep;
71 
72  rendNetwork = new RendNetwork( this );
73  m_mainLayout->addWidget( rendNetwork, 4 );
74 
75  mixerDialog = new MixerDialog( enet, this );
76  m_mainLayout->addWidget( mixerDialog );
77  mixerDialog->hide();
78 
79  statusb = new QLabel("",this);
80  m_mainLayout->addWidget(statusb);
81 
82  connect(rendNetwork, SIGNAL(selectedneuronsChanged()), this, SLOT(updatetoolb()) );
83 }
84 
85 
86 NetworkDialog::~NetworkDialog()
87 {
88 }
89 
90 /*
91 void NetworkDialog::keyReleaseEvent(QKeyEvent* event)
92 {
93 
94  if (event->matches(QKeySequence::Print)) {
95  // Taking a screenshow of the widget
96  shotWidget();
97  } else {
98  // Calling parent function
99  QDialog::keyReleaseEvent(event);
100  }
101 }
102 */
103 
104 /*
105 void NetworkDialog::shotWidget()
106 {
107 
108  // Taking a screenshot of this widget
109  QPixmap shot(size());
110  render(&shot);
111 
112  // Asking the user where to save the shot
113  QString fileName = QFileDialog::getSaveFileName(this, tr("Save Shot"), "./widget.png", tr("Images (*.png *.xpm *.jpg)"));
114  if (!fileName.isEmpty()) {
115  shot.save(fileName);
116 
117  QMessageBox::information(this, QString("File Saved"), QString("The widget shot has been saved"));
118  }
119 }*/
120 
121 
122 void NetworkDialog::error(const char *emessage)
123 {
124  QMessageBox::about(this, "ERROR", emessage);
125 }
126 
127 void NetworkDialog::warning(const char *emessage)
128 {
129  QMessageBox::about(this, "WARNING", emessage);
130 }
131 
132 
133 void NetworkDialog::createToolBars()
134 {
135 
136  char stblock[1024];
137  int b;
138 
139  m_toolBar->addAction(openAct);
140  m_toolBar->addAction(saveAct);
141 
142  cblockAct = new QComboBox( m_toolBar );
143  cblockAct->addItems(QStringList() << "blocks list");
144  for (b=0; b < enet->net_nblocks; b++)
145  {
146  block_name(b, stblock);
147  cblockAct->addItems(QStringList() << stblock);
148  }
149  connect( cblockAct, SIGNAL(currentIndexChanged(int)), this, SLOT(selblock_changed(int)) );
150  connect(this, SIGNAL(selectedblockChanged()), this, SLOT(updateblocktype()) );
151 
152  m_toolBar->addWidget( cblockAct );
153 
154  blocktypeAct = new QComboBox( m_toolBar );
155  blocktypeAct->addItems(QStringList() << "block type");
156  blocktypeAct->addItems(QStringList() << "genetic" << "fixed" << "back-prop" );
157  connect(blocktypeAct, SIGNAL(currentIndexChanged(int)), this, SLOT(changeblocktype(int)) );
158  m_toolBar->addWidget( blocktypeAct );
159 
160  neurontypeAct = new QComboBox( m_toolBar );
161  neurontypeAct->addItems( QStringList() << "neuron type");
162  neurontypeAct->addItems( QStringList() << "sigmoid" << "integrator" << "binary" << "sigmoid flat" );
163  connect( neurontypeAct, SIGNAL(currentIndexChanged(int)), this, SLOT(set_neurontype(int)) );
164  m_toolBar->addWidget( neurontypeAct );
165 
166  m_toolBar->addAction(display_labelAct);
167  m_toolBar->addAction(display_weightAct);
168  m_toolBar->addAction(display_deltaAct);
169  m_toolBar->addAction(display_biasAct);
170  m_toolBar->addAction(display_gainAct);
171  m_toolBar->addAction(set_neurondisplayAct);
172  m_toolBar->addAction(set_lesionAct);
173  m_toolBar->addAction(set_neuronbiasAct);
174  m_toolBar->addAction(set_neurongainAct);
175  m_toolBar->addAction(add_ublockAct);
176  m_toolBar->addAction(add_cblockAct);
177  m_toolBar->addAction(add_gblockAct);
178  m_toolBar->addAction(erase_Act);
179 }
180 
181 void NetworkDialog::createActions()
182 {
183 
184 
185  openAct = new QAction(QIcon(":/evorobot/open.png"), tr("&Open"), this);
186 
187 
188  openAct->setStatusTip(tr("Open a network architecture or a phenotype file"));
189  connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
190 
191  saveAct = new QAction(QIcon(":/evorobot/save.png"), tr("&Save"), this);
192  saveAct->setStatusTip(tr("Save the network architecture or the phenotype from a file"));
193  connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
194 
195  set_neurondisplayAct = new QAction(QIcon(":/evorobot/show.png"), tr("&Set/Unset neurons to be displayed as graph"), this);
196  set_neurondisplayAct->setShortcut(tr("Ctrl+N"));
197  set_neurondisplayAct->setStatusTip(tr("Select/Deselect neurons to be displayed as graph"));
198  connect(set_neurondisplayAct, SIGNAL(triggered()), this, SLOT(set_neurondisplay()));
199 
200  set_neurongainAct = new QAction(QIcon(":/evorobot/gain.png"), tr("&Add/Remove neurons gain"), this);
201  set_neurongainAct->setShortcut(tr("Ctrl+G"));
202  set_neurongainAct->setStatusTip(tr("Add/Remove neurons gain"));
203  connect(set_neurongainAct, SIGNAL(triggered()), this, SLOT(set_neurongain()));
204 
205  set_neuronbiasAct = new QAction(QIcon(":/evorobot/bias.png"), tr("&Add/Remove neurons biases"), this);
206  set_neuronbiasAct->setShortcut(tr("Ctrl+B"));
207  set_neuronbiasAct->setStatusTip(tr("Add/Remove neurons bias"));
208  connect(set_neuronbiasAct, SIGNAL(triggered()), this, SLOT(set_neuronbias()));
209 
210  set_lesionAct = new QAction(QIcon(":/evorobot/lesion.png"), tr("&Lesion/Restore neurons"), this);
211  set_lesionAct->setShortcut(tr("Ctrl+B"));
212  set_lesionAct->setStatusTip(tr("Lesion/Restore neurons"));
213  connect(set_lesionAct, SIGNAL(triggered()), this, SLOT(set_lesion()));
214 
215  display_labelAct = new QAction(QIcon(":/evorobot/label.png"), tr("&Display/Undisplay neuron labels"), this);
216  display_labelAct->setShortcut(tr("Ctrl+L"));
217  display_labelAct->setStatusTip(tr("Display neuron labels"));
218  connect(display_labelAct, SIGNAL(triggered()), this, SLOT(display_label()));
219 
220  display_weightAct = new QAction(QIcon(":/evorobot/weight.png"), tr("&Display/Undisplay weights"), this);
221  display_weightAct->setShortcut(tr("Ctrl+W"));
222  display_weightAct->setStatusTip(tr("Display the incoming and outcoming weight of a neuron"));
223  connect(display_weightAct, SIGNAL(triggered()), this, SLOT(display_weight()));
224 
225  display_deltaAct = new QAction(QIcon(":/evorobot/ddelta.png"), tr("&Display/Undisplay neurons delta"), this);
226  display_deltaAct->setShortcut(tr("Ctrl+Y"));
227  display_deltaAct->setStatusTip(tr("Display neurons delta"));
228  connect(display_deltaAct, SIGNAL(triggered()), this, SLOT(display_delta()));
229 
230  display_biasAct = new QAction(QIcon(":/evorobot/dbias.png"), tr("&Display/Undisplay biases"), this);
231  display_biasAct->setShortcut(tr("Ctrl+Z"));
232  display_biasAct->setStatusTip(tr("Display neurons biases"));
233  connect(display_biasAct, SIGNAL(triggered()), this, SLOT(display_bias()));
234 
235  display_gainAct = new QAction(QIcon(":/evorobot/dgain.png"), tr("&Display/Undisplay gains"), this);
236  display_gainAct->setShortcut(tr("Ctrl+G"));
237  display_gainAct->setStatusTip(tr("Display neurons gains"));
238  connect(display_gainAct, SIGNAL(triggered()), this, SLOT(display_gain()));
239 
240  erase_Act = new QAction(QIcon(":/evorobot/erase.png"), tr("&Erase"), this);
241  erase_Act->setShortcut(tr("Ctrl+E"));
242  erase_Act->setStatusTip(tr("Erase all or selected properties"));
243  connect(erase_Act, SIGNAL(triggered()), this, SLOT(erase()));
244 
245  add_ublockAct = new QAction(QIcon(":/evorobot/addublock.png"), tr("&Add Update Block"), this);
246  add_ublockAct->setShortcut(tr("Ctrl+A"));
247  add_ublockAct->setStatusTip(tr("add an update block"));
248  connect(add_ublockAct, SIGNAL(triggered()), this, SLOT(add_ublock()));
249 
250  add_cblockAct = new QAction(QIcon(":/evorobot/addblock.png"), tr("&Add Connection Block"), this);
251  add_cblockAct->setShortcut(tr("Ctrl+A"));
252  add_cblockAct->setStatusTip(tr("add a connection block"));
253  connect(add_cblockAct, SIGNAL(triggered()), this, SLOT(add_cblock()));
254 
255  add_gblockAct = new QAction(QIcon(":/evorobot/gainblock.png"), tr("&Add a gain block"), this);
256  add_gblockAct->setShortcut(tr("Ctrl+G"));
257  add_gblockAct->setStatusTip(tr("add a gain block"));
258  connect(add_gblockAct, SIGNAL(triggered()), this, SLOT(add_gblock()));
259 
260  increasevAct = new QShortcut(tr("+"), this);
261  connect(increasevAct, SIGNAL(activated()), this, SLOT(increasev()));
262 
263  decreasevAct = new QShortcut(tr("-"), this);
264  connect(decreasevAct, SIGNAL(activated()), this, SLOT(decreasev()));
265 
266  //connect(rendNetwork, SIGNAL(selectedneuronsChanged()), this, SLOT(updatetoolb()) );
267 
268 }
269 
270 // return the current selected block (-1 in case of no selection)
271 int NetworkDialog::getcblock()
272 {
273  return(cblockAct->currentIndex() - 1);
274 }
275 
276 
277 // update the neuron type combo box status
278 // this method is triggered when the user select a neuron
279 void NetworkDialog::updatetoolb()
280 {
281 
282  // we set the index of the neuron-type combo box to that of the first selected neuron
283  // this trigger the set_neurontype function
284  if (cneuronn == 1)
285  {
286  neurontypeAct->setCurrentIndex(enet->neurontype[cneuron[0]]+1);
287  }
288 
289 }
290 
291 // update the block type combo box status
292 // this function is triggered when a new block is selected
293 void NetworkDialog::updateblocktype()
294 {
295 
296  int cb;
297 
298  cb = cblockAct->currentIndex();
299 
300  // we set the type combobox index on the basis of the type current selected block
301  blocktypeAct->setCurrentIndex(enet->net_block[cb][5]+1);
302 
303 }
304 
305 
306 // modify the type of a block
307 // this function is triggered by the user
308 void NetworkDialog::changeblocktype(int t)
309 {
310 
311  int cb;
312  int oldt;
313 
314  cb = cblockAct->currentIndex();
315 
316  if (t > 0 && cb > 0 /*&& blocktypeauto == 0 */)
317  {
318  oldt = enet->net_block[cb][5];
319  enet->net_block[cb][5] = t - 1;
320  if (oldt != t - 1)
321  {
322  statusb->setText(QString("The type of the selected block has been modified"));
323  }
324  }
325 }
326 
327 // define or undefine neurons to be displayed
328 void NetworkDialog::set_neurondisplay()
329 {
330  int i;
331 
332  if (cneuronn == 1)
333  {
334  if (enet->neurondisplay[cneuron[0]] == 1)
335  enet->neurondisplay[cneuron[0]] = 0;
336  else
337  enet->neurondisplay[cneuron[0]] = 1;
338  }
339  if (cneuronn == 2)
340  {
341  if (enet->neurondisplay[cneuron[0]] == 1)
342  for (i=cneuron[0]; i <= cneuron[1]; i++)
343  enet->neurondisplay[i] = 0;
344  else
345  for (i=cneuron[0]; i <= cneuron[1]; i++)
346  enet->neurondisplay[i] = 1;
347  }
348  if (cneuronn < 1 || cneuronn > 2)
349  warning("you should select one neuron or one block of neurons first");
350  else
351  statusb->setText(QString("Neurons to be monitored have been updated"));
352 
353  cneuronn = 0;
354  rendNetwork->update();
355 
356 }
357 // change neurons' type
358 void NetworkDialog::set_neurontype(int t)
359 {
360 
361  int oldt;
362 
363  if (t > 0) // nothing is done if combobox is reset to the "neuron type" title slot
364  {
365  oldt = enet->neurontype[cneuron[0]];
366  if (cneuronn == 1)
367  {
368  enet->neurontype[cneuron[0]] = t-1;
369  }
370  if (cneuronn == 2)
371  {
372  for (int i=cneuron[0]; i <= cneuron[1]; i++)
373  {
374  enet->neurontype[i] = t-1;
375  }
376  }
377  if (cneuronn < 1 || cneuronn > 2)
378  warning("you should select one neuron or one block of neurons first");
379  else
380  {
381  if (oldt != enet->neurontype[cneuron[0]])
382  statusb->setText(QString("Neurons' type updated"));
383  }
384  cneuronn = 0;
385  rendNetwork->update();
386  }
387 
388 }
389 
390 
391 // manage actions associated to the selection of a block
392 // the signal trigger the block type update function
393 void NetworkDialog::selblock_changed(int t)
394 {
395  if (t > 0)
396  statusb->setText(QString("Block selected"));
397  emit selectedblockChanged();
398  rendNetwork->update();
399 }
400 
401 // define or undefine neurons gain
402 void NetworkDialog::set_neurongain()
403 {
404  int i;
405 
406  if (cneuronn < 1 || cneuronn > 2)
407  {
408  warning("you should select one neuron or one block of neurons first");
409  }
410  else
411  {
412  if (cneuronn == 1)
413  {
414  if (enet->neurongain[cneuron[0]] == 1)
415  {
416  enet->neurongain[cneuron[0]] = 0;
417  statusb->setText(QString("Neuron's gain eliminated"));
418  }
419  else
420  {
421  enet->neurongain[cneuron[0]] = 1;
422  statusb->setText(QString("Neuron's gain added"));
423  }
424  }
425  if (cneuronn == 2)
426  {
427  if (enet->neurongain[cneuron[0]] == 1)
428  {
429  for (i=cneuron[0]; i <= cneuron[1]; i++)
430  enet->neurongain[i] = 0;
431  statusb->setText(QString("Neurons' gain eliminated"));
432  }
433  else
434  {
435  for (i=cneuron[0]; i <= cneuron[1]; i++)
436  enet->neurongain[i] = 1;
437  statusb->setText(QString("Neurons' gain added"));
438 
439  }
440  }
441  }
442 
443  cneuronn = 0;
444  rendNetwork->update();
445 
446 }
447 
448 
449 // define or undefine neurons bias
450 void NetworkDialog::set_neuronbias()
451 {
452  int i;
453 
454  if (cneuronn < 1 || cneuronn > 2)
455  {
456  warning("you should select one neuron or one block of neurons first");
457  }
458  else
459  {
460  if (cneuronn == 1)
461  {
462  if (enet->neuronbias[cneuron[0]] == 1)
463  {
464  enet->neuronbias[cneuron[0]] = 0;
465  statusb->setText(QString("Neuron's bias eliminated"));
466  }
467  else
468  {
469  enet->neuronbias[cneuron[0]] = 1;
470  statusb->setText(QString("Neuron's bias added"));
471  }
472  }
473  if (cneuronn == 2)
474  {
475  if (enet->neuronbias[cneuron[0]] == 1)
476  {
477  for (i=cneuron[0]; i <= cneuron[1]; i++)
478  enet->neuronbias[i] = 0;
479  statusb->setText(QString("Neurons' bias eliminated"));
480  }
481  else
482  {
483  for (i=cneuron[0]; i <= cneuron[1]; i++)
484  enet->neuronbias[i] = 1;
485  statusb->setText(QString("Neurons' bias added"));
486  }
487  }
488  cneuronn = 0;
489  rendNetwork->update();
490  }
491 
492 }
493 
494 /*
495  * Lesion/unlesion neurons
496  */
497 void NetworkDialog::set_lesion()
498 {
499 
500  if (enet->neuronlesions == 0)
501  {
502  if (cneuronn == 1)
503  {
504  enet->neuronlesion[cneuron[0]]=!enet->neuronlesion[cneuron[0]];
505  cneuronn = 0;
506  enet->neuronlesions = 1;
507  openMixer();
508  statusb->setText(QString("Neuron's lesioned"));
509  rendNetwork->update();
510  }
511  else
512  if (cneuronn == 2)
513  {
514  for(int ls = cneuron[0]; ls <= cneuron[1]; ls++)
515  {
516  enet->neuronlesion[ls] = !enet->neuronlesion[ls];
517  enet->neuronlesions++;
518  }
519  cneuronn = 0;
520  openMixer();
521  statusb->setText(QString("Neurons' lesioned"));
522  rendNetwork->update();
523  }
524  else
525  {
526  warning("you should select one neuron or one block of neurons first");
527  }
528  }
529  else
530  {
531  enet->neuronlesions = 0;
532  for (int i = 0; i < enet->nneurons; i++)
533  {
534  enet->neuronlesion[i]=false;
535  enet->neuronlesionVal[i]=0.0;
536  }
537  mixerDialog->hide();
538  statusb->setText(QString("Neurons un-lesioned"));
539  rendNetwork->update();
540  }
541 }
542 
543 // Display neurons label
544 void NetworkDialog::display_label()
545 {
546 
547  pseudomode = 0;
548  cneuronn = 0;
549  pseudo_activate_net();
550  statusb->setText(QString("Neurons labels displayed"));
551  rendNetwork->update();
552 
553 }
554 
555 
556 
557 // Display/Undisplay neurons delta
558 void NetworkDialog::display_delta()
559 {
560 
561  if (cneuronn == 1 || cneuronn == 2)
562  {
563  pseudomode = 1;
564  pseudo_activate_net();
565  openMixer();
566  cneuronn = 0;
567  statusb->setText(QString("Neurons' timeconstants weight displayed"));
568  rendNetwork->update();
569  }
570  else
571  {
572  warning("you should select one neuron or one block of neurons first");
573  }
574 }
575 
576 
577 // Display/Undisplay the weights of a neuron
578 void NetworkDialog::display_weight()
579 {
580 
581  if (cneuronn == 4)
582  {
583  pseudomode = 2;
584  pseudo_activate_net();
585  statusb->setText(QString("Connections weights displayed"));
586  openMixer();
587  cneuronn = 0;
588  rendNetwork->update();
589  }
590  else
591  {
592  warning("you should select the receiving and sending block of neurons first (4 neurons)");
593  }
594 }
595 
596 // Display/Undisplay neurons biases
597 void NetworkDialog::display_bias()
598 {
599 
600  if (cneuronn == 1 || cneuronn == 2)
601  {
602  pseudomode = 3;
603  pseudo_activate_net();
604  statusb->setText(QString("Biases weight displayed"));
605  rendNetwork->update();
606  openMixer();
607  }
608  else
609  {
610  warning("you should select one neuron or one block of neurons first");
611  }
612 
613 }
614 
615 // Display/Undisplay neurons gains
616 void NetworkDialog::display_gain()
617 {
618 
619 
620  if (cneuronn == 1 || cneuronn == 2)
621  {
622  pseudomode = 4;
623  pseudo_activate_net();
624  openMixer();
625  cneuronn = 0;
626  statusb->setText(QString("Neurons' gain weight displayed"));
627  rendNetwork->update();
628  }
629  else
630  {
631  warning("you should select one neuron or one block of neurons first");
632  }
633 }
634 
635 
636 // Erase a selected block or all blocks (when no block is selected)
637 void NetworkDialog::erase()
638 {
639 
640  int cblock;
641  int i, ii;
642  int bb;
643 
644 
645  cblock = getcblock();
646 
647  if (cblock < 0)
648  {
649  // we erase all blocks and reset neurons' properties
650  enet->net_nblocks = 0;
651  cblockAct->clear();
652  cblockAct->addItems(QStringList() << "blocks list");
653  for(i=0;i < enet->nneurons; i++)
654  {
655  enet->neuronbias[i] = 0;
656  enet->neurontype[i] = 0;
657  enet->neurongain[i] = 0;
658  enet->neurondisplay[i] = 1;
659  }
660  statusb->setText(QString("All blocks erased and neurons' properties reset"));
661  }
662  else
663  {
664  // we erase the selected block
665  cblockAct->removeItem(cblock+1);
666  cblockAct->setCurrentIndex(0);
667  for (bb=cblock; bb < (enet->net_nblocks - 1); bb++)
668  for (ii=0; ii < 6; ii++)
669  enet->net_block[bb][ii] = enet->net_block[bb+1][ii];
670  enet->net_nblocks--;
671  statusb->setText(QString("Selected block erased"));
672  }
673  rendNetwork->update();
674 }
675 
676 
677 // Add an update block
678 void NetworkDialog::add_ublock()
679 {
680 
681  int i,ii;
682  char stblock[1024];
683  int cblock;
684 
685  if (cneuronn != 1 && cneuronn != 2)
686  {
687  warning("you should select a a lock (2 neurons) first");
688  return;
689  }
690 
691  cblock = getcblock(); // we add the new block before the selected block
692  if (cblock < 0)
693  cblock = enet->net_nblocks; // or we add it at the end of the block list
694 
695  if (cneuronn == 1)
696  {
697  for(i=enet->net_nblocks; i > cblock; i--)
698  for(ii=0; ii<6; ii++)
699  enet->net_block[i][ii] = enet->net_block[i-1][ii];
700  enet->net_block[cblock][0] = 1;
701  enet->net_block[cblock][1] = cneuron[0];
702  enet->net_block[cblock][2] = 1;
703  enet->net_block[cblock][3] = 0;
704  enet->net_block[cblock][4] = 0;
705  enet->net_block[cblock][5] = 0;
706  block_name(cblock, stblock);
707  cblockAct->insertItems(cblock+1, QStringList() << stblock);
708  enet->net_nblocks++;
709  cneuronn = 0;
710  }
711 
712  if (cneuronn == 2)
713  {
714  for(i=enet->net_nblocks; i > cblock; i--)
715  for(ii=0; ii<6; ii++)
716  enet->net_block[i][ii] = enet->net_block[i-1][ii];
717  enet->net_block[cblock][0] = 1;
718  enet->net_block[cblock][1] = cneuron[0];
719  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
720  enet->net_block[cblock][3] = 0;
721  enet->net_block[cblock][4] = 0;
722  enet->net_block[cblock][5] = 0;
723  block_name(cblock, stblock);
724  cblockAct->insertItems(cblock+1, QStringList() << stblock);
725  enet->net_nblocks++;
726  cneuronn = 0;
727  }
728 
729  cblockAct->setCurrentIndex(0);
730  statusb->setText(QString("Update block added"));
731  rendNetwork->update();
732 }
733 
734 
735 // Add a connection block
736 void NetworkDialog::add_cblock()
737 {
738 
739  int i,ii;
740  char stblock[1024];
741  int cblock;
742 
743 
744  if (cneuronn != 4)
745  {
746  warning("you should select the receiving and sending blocks (4 neurons) first");
747  return;
748  }
749 
750  cblock = getcblock(); // we add the new block before the selected block
751  printf("cblock %d\n", cblock);
752  if (cblock < 0)
753  cblock = enet->net_nblocks; // or we add it at the end of the block list
754 
755 
756  if (cneuronn == 4)
757  {
758  for(i=enet->net_nblocks; i > cblock; i--)
759  for(ii=0; ii<6; ii++)
760  enet->net_block[i][ii] = enet->net_block[i-1][ii];
761  enet->net_block[cblock][0] = 0;
762  enet->net_block[cblock][1] = cneuron[0];
763  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
764  enet->net_block[cblock][3] = cneuron[2];
765  enet->net_block[cblock][4] = cneuron[3] - cneuron[2] + 1;
766  enet->net_block[cblock][5] = 0;
767  block_name(cblock, stblock);
768  cblockAct->insertItems(cblock+1, QStringList() << stblock);
769  enet->net_nblocks++;
770  cneuronn = 0;
771  }
772 
773  cblockAct->setCurrentIndex(0);
774  statusb->setText(QString("Connection block added"));
775  rendNetwork->update();
776 }
777 
778 // Add a gain block
779 void NetworkDialog::add_gblock()
780 {
781 
782  int i,ii;
783  char stblock[1024];
784  int cblock;
785 
786  if (cneuronn != 2 && cneuronn != 3)
787  {
788  warning("you should select a block (2 neurons) and eventually a third neuron first");
789  return;
790  }
791 
792  cblock = getcblock(); // we add the new block before the selected block
793  if (cblock < 0)
794  cblock = enet->net_nblocks; // or we add it at the end of the block list
795 
796 
797  // a block with 2 selected neurons operates by making the gain of all the neurons of the block equal to that of the first neuron of the block
798  if (cneuronn == 2)
799  {
800  for(i=enet->net_nblocks; i > cblock; i--)
801  for(ii=0; ii<6; ii++)
802  enet->net_block[i][ii] = enet->net_block[i-1][ii];
803  enet->net_block[cblock][0] = 2;
804  enet->net_block[cblock][1] = cneuron[0];
805  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
806  enet->net_block[cblock][3] = 0;
807  enet->net_block[cblock][4] = 0;
808  enet->net_block[cblock][5] = 0;
809  block_name(cblock, stblock);
810  cblockAct->insertItems(cblock+1, QStringList() << stblock);
811  enet->net_nblocks++;
812  cneuronn = 0;
813  }
814  // a block with 3 selected neurons operates by making the gain the neurons of the block equal the to activation state of the 3rd neuron at time t-1
815  if (cneuronn == 3)
816  {
817  for(i=enet->net_nblocks; i > cblock; i--)
818  for(ii=0; ii<6; ii++)
819  enet->net_block[i][ii] = enet->net_block[i-1][ii];
820  enet->net_block[cblock][0] = 3;
821  enet->net_block[cblock][1] = cneuron[0];
822  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
823  enet->net_block[cblock][3] = cneuron[2];
824  enet->net_block[cblock][4] = 0;
825  enet->net_block[cblock][5] = 0;
826  block_name(cblock, stblock);
827  cblockAct->insertItems(cblock+1, QStringList() << stblock);
828  enet->net_nblocks++;
829  cneuronn = 0;
830  }
831 
832  cblockAct->setCurrentIndex(0);
833  statusb->setText(QString("Gain block added"));
834  rendNetwork->update();
835 }
836 
837 
838 /*
839  * open a .net or .phe file
840  */
841 void NetworkDialog::open()
842 {
843 
844  char *f;
845  QByteArray filen;
846  char filename[256];
847 
848 
849  QString fileName = QFileDialog::getOpenFileName(this,
850  "Choose a filename to open",
851  "",
852  "*.net *.phe");
853 
854 
855  if (fileName.endsWith("net"))
856  {
857  filen = fileName.toAscii();
858  f = filen.data();
859  strcpy(filename, f);
860  enet->load_net_blocks(filename, 0);
861  statusb->setText(QString("File %1 loaded").arg(filename));
862  }
863  else
864  if (fileName.endsWith("phe"))
865  {
866  filen = fileName.toAscii();
867  f = filen.data();
868  strcpy(filename, f);
869  enet->load_net_blocks(filename, 1);
870  statusb->setText(QString("File %1 loaded").arg(filename));
871  }
872 
873 }
874 
875 /*
876  * save a .net or .phe file
877  */
878 void NetworkDialog::save()
879 {
880 
881  char *f;
882  QByteArray filen;
883  char filename[256];
884 
885 
886  QString fileName = QFileDialog::getSaveFileName(this,
887  "Choose a filename to save",
888  "",
889  "*.net *.phe");
890 
891 
892  if (fileName.endsWith("net"))
893  {
894  filen = fileName.toAscii();
895  f = filen.data();
896  strcpy(filename, f);
897  enet->save_net_blocks(filename, 0);
898  statusb->setText(QString("File %1 saved").arg(filename));
899 
900  }
901  else
902  if (fileName.endsWith("phe"))
903  {
904  filen = fileName.toAscii();
905  f = filen.data();
906  strcpy(filename, f);
907  enet->save_net_blocks(filename, 1);
908  statusb->setText(QString("File %1 saved").arg(filename));
909  }
910 
911 }
912 
913 // Increase a selected value
914 void NetworkDialog::increasev()
915 {
916  float **gp;
917  float *v;
918 
919 
920  // when 2 neurons are selected we assume that the user want to change a connection weight
921  if (cneuronn == 2)
922  {
923  pseudomode = 2;
924  pseudo_activate_net();
925  if (enet->nselected == 1)
926  {
927  gp = enet->selectedp;
928  v = *gp;
929  *v += ((enet->wrange * 2.0f) / 256.0f);
930  pseudo_activate_net();
931  rendNetwork->update();
932  }
933  }
934  // when 1 neuron is selected we modify the bias of the neuron,
935  // or the delta or the gain of the neuron (if the user previously pushed the delta or gain buttons, respectively)
936  if (cneuronn == 1)
937  {
938  if (pseudomode != 1 && pseudomode != 4)
939  pseudomode = 3;
940  pseudo_activate_net();
941  if (enet->nselected == 1)
942  {
943  gp = enet->selectedp;
944  v = *gp;
945  *v += ((enet->wrange * 2.0f) / 256.0f);
946  pseudo_activate_net();
947  rendNetwork->update();
948  }
949  }
950 
951 }
952 
953 // Decrease a selected value
954 void NetworkDialog::decreasev()
955 {
956 
957  float **gp;
958  float *v;
959 
960 
961  // when 2 neurons are selected we assume that the user want to change a connection weight
962  if (cneuronn == 2)
963  {
964  pseudomode = 2;
965  pseudo_activate_net();
966  if (enet->nselected == 1)
967  {
968  gp = enet->selectedp;
969  v = *gp;
970  *v -= ((enet->wrange * 2.0f) / 256.0f);
971  pseudo_activate_net();
972  rendNetwork->update();
973  }
974  }
975  // when 1 neuron is selected we modify the bias of the neuron,
976  // or the delta or the gain of the neuron (if the user previously pushed the delta or gain buttons, respectively)
977  if (cneuronn == 1)
978  {
979  if (pseudomode != 1 && pseudomode != 4)
980  pseudomode = 3;
981  pseudo_activate_net();
982  if (enet->nselected == 1)
983  {
984  gp = enet->selectedp;
985  v = *gp;
986  *v -= ((enet->wrange * 2.0f) / 256.0f);
987  pseudo_activate_net();
988  rendNetwork->update();
989  }
990  }
991 
992 }
993 
994 // It return the name/description of an existing block
995 void NetworkDialog::block_name(int b, char *st)
996 {
997  switch(enet->net_block[b][0])
998  {
999  case 0:
1000  sprintf(st,"c) %s_%s %s_%s", enet->neuronl[enet->net_block[b][1]], enet->neuronl[enet->net_block[b][1]+enet->net_block[b][2]-1],enet->neuronl[enet->net_block[b][3]],enet->neuronl[enet->net_block[b][3]+enet->net_block[b][4]-1]);
1001  break;
1002  case 1:
1003  sprintf(st,"u) %s_%s", enet->neuronl[enet->net_block[b][1]], enet->neuronl[enet->net_block[b][1]+enet->net_block[b][2]-1]);
1004  break;
1005  case 2:
1006  sprintf(st,"g) %s_%s", enet->neuronl[enet->net_block[b][1]], enet->neuronl[enet->net_block[b][1]+enet->net_block[b][2]-1]);
1007  break;
1008  case 3:
1009  sprintf(st,"g) %s_%s %s", enet->neuronl[enet->net_block[b][1]], enet->neuronl[enet->net_block[b][1]+enet->net_block[b][2]-1],enet->neuronl[enet->net_block[b][3]]);
1010  break;
1011  default:
1012  sprintf(st,"undefined block type");
1013  break;
1014  }
1015 
1016 }
1017 
1018 /*
1019  * This function replace the current neuron labels string with the user's selected parameter:
1020  * (timeconstant, weight, bias, gain). Selected parameters are also stored in the selectedp
1021  * pointer list.
1022  */
1023 void
1024 NetworkDialog::pseudo_activate_net()
1025 
1026 {
1027  int i;
1028  int t;
1029  int b;
1030  float delta;
1031  float gain;
1032  float bias;
1033  float **gp;
1034  int ddelta=0;
1035  int dweight=0;
1036  int dbias=0;
1037  int dgain=0;
1038  float *p;
1039 
1040  switch(pseudomode)
1041  {
1042  case 1:
1043  ddelta = 1;
1044  break;
1045  case 2:
1046  dweight = 1;
1047  break;
1048  case 3:
1049  dbias = 1;
1050  break;
1051  case 4:
1052  dgain = 1;
1053  break;
1054  }
1055 
1056  p = freep;
1057  gp = enet->selectedp;
1058  enet->nselected = 0;
1059 
1060  for(i=0;i < enet->nneurons;i++)
1061  strcpy(neuroncl[i],enet->neuronl[i]);
1062 
1063  //for(i=0;i < enet->nneurons;i++)
1064  // updated[i] = 0;
1065 
1066  // gain (from the first to the second selected neuron)
1067  for(i=0;i < enet->nneurons;i++)
1068  {
1069  if (enet->neurongain[i] == 1)
1070  {
1071  if (dgain > 0 && ((cneuronn == 1 && i == cneuron[0]) || (cneuronn == 2 && i >= cneuron[0] && i <= cneuron[1])))
1072  {
1073  gain = (fabs((double) *p) / enet->wrange) * enet->grange;
1074  sprintf(neuroncl[i],"%.1f",gain);
1075  *gp = p;
1076  gp++;
1077  enet->nselected++;
1078  }
1079  p++;
1080  }
1081  }
1082 
1083  // biases (from the first to the second selected neuron)
1084  for(i=0;i < enet->nneurons;i++)
1085  {
1086  if (enet->neuronbias[i] == 1)
1087  {
1088  if (dbias > 0 && ((cneuronn == 1 && i == cneuron[0]) || (cneuronn == 2 && i >= cneuron[0] && i <= cneuron[1])))
1089  {
1090  bias = (fabs((double) *p) / enet->wrange) * enet->brange;
1091  sprintf(neuroncl[i],"%.1f",bias);
1092  *gp = p;
1093  gp++;
1094  enet->nselected++;
1095  }
1096  p++;
1097  }
1098  }
1099 
1100  // blocks
1101  for (b=0; b < enet->net_nblocks; b++)
1102  {
1103  // connection block
1104  if (enet->net_block[b][0] == 0)
1105  {
1106  for(t=enet->net_block[b][1]; t < enet->net_block[b][1] + enet->net_block[b][2];t++)
1107  for(i=enet->net_block[b][3]; i < enet->net_block[b][3] + enet->net_block[b][4];i++)
1108  {
1109  // weights (4 neurons, receiving block, sending block)
1110  if (dweight == 1 && cneuronn == 4 && (t >= cneuron[0] && t <= cneuron[1]) && (i >= cneuron[2] && i <= cneuron[3]))
1111  {
1112  // values can be visualized in the label only if a single receiving neuron has been selected
1113  if (cneuron[0] == cneuron[1])
1114  sprintf(neuroncl[i],"%.1f",*p);
1115  *gp = p;
1116  gp++;
1117  enet->nselected++;
1118  }
1119  p++;
1120  }
1121  }
1122  // update block
1123  if (enet->net_block[b][0] == 1)
1124  {
1125  for(t=enet->net_block[b][1]; t < (enet->net_block[b][1] + enet->net_block[b][2]); t++)
1126  {
1127  //updated[t] +=1;
1128  if (enet->neurontype[t] != 1)
1129  {
1130  ;
1131  }
1132  else
1133  {
1134  // timeconstant (from the first to the second selected neuron)
1135  delta = (float) (fabs((double) *p) / enet->wrange);
1136  if (ddelta > 0 && ((cneuronn == 1 && t == cneuron[0]) || (cneuronn == 2 && t >= cneuron[0] && t <= cneuron[1])))
1137  {
1138  sprintf(neuroncl[t],"%.1f",delta);
1139  *gp = p;
1140  gp++;
1141  enet->nselected++;
1142  }
1143  p++;
1144  }
1145  }
1146  }
1147  }
1148 
1149 
1150 }
1151 
1152 /*
1153  * Mixer for lesioned or freezed neurons
1154  */
1155 void NetworkDialog::openMixer()
1156 {
1157 
1158  //mixerDialog=new MixerDialog(this->enet, this);
1159  mixerDialog->setUpMixer();
1160  mixerDialog->show();
1161  rendNetwork->update();
1162 
1163 }
1164 
1165 
1166 
1167 // -----------------------------------------------------
1168 // Widget RendNetwork
1169 // -----------------------------------------------------
1170 
1171 RendNetwork::RendNetwork( NetworkDialog* networkDialog, QWidget *parent)
1172  : QWidget(parent)
1173 {
1174  shape = Polygon;
1175  antialiased = false;
1176  pixmap.load(":/evorobot/qt-logo.png");
1177 
1178  setBackgroundRole(QPalette::Base);
1179  this->networkDialog = networkDialog;
1180 
1181  rnmousex = 20000;
1182  rnmousey = 30000;
1183 }
1184 
1185 QSize RendNetwork::minimumSizeHint() const
1186 {
1187  return QSize(250, 250);
1188 }
1189 
1190 QSize RendNetwork::sizeHint() const
1191 {
1192  return QSize(550, 500);
1193 }
1194 
1195 void RendNetwork::setShape(Shape shape)
1196 {
1197  this->shape = shape;
1198  update();
1199 }
1200 
1201 void RendNetwork::setPen(const QPen &pen)
1202 {
1203  this->pen = pen;
1204  update();
1205 }
1206 
1207 
1208 
1209 void RendNetwork::setBrush(const QBrush &brush)
1210 {
1211  this->brush = brush;
1212  update();
1213 }
1214 
1215 void RendNetwork::setAntialiased(bool antialiased)
1216 {
1217  this->antialiased = antialiased;
1218  update();
1219 }
1220 
1221 void RendNetwork::setTransformed(bool transformed)
1222 {
1223  this->transformed = transformed;
1224  update();
1225 }
1226 
1227 
1228 void RendNetwork::paintEvent(QPaintEvent *)
1229 {
1230 
1231 
1232  int i;
1233  int t,b;
1234  int sx,sy,dx,dy;
1235  float *p;
1236  int cr,cb,cg;
1237  int wid = 1;
1238  float w;
1239  int selectedneurons[2];
1240  QPainter painter(this);
1241 
1242  QRect labelxy(0,0,30,20); // neuron labels
1243  QPoint pxy;
1244  painter.setPen(pen);
1245  QPen pen(Qt::black, 1); // black solid line, 1 pixels wide
1246  painter.setPen(pen);
1247  selectedneurons[0] = selectedneurons[1] = -1;
1248  // set the scale
1249  if (networkDialog->enet->drawnxmax > 0 && networkDialog->enet->drawnymax > 0)
1250  {
1251  networkDialog->cscaley = height() / (float) networkDialog->enet->drawnymax;
1252  networkDialog->cscalex = width() / (float) networkDialog->enet->drawnxmax;
1253  painter.scale(networkDialog->cscalex, networkDialog->cscaley);
1254  }
1255  else
1256  {
1257  painter.scale(1.0,1.0);
1258  }
1259  painter.setPen(Qt::gray);
1260  // extract gain and biases
1261  p = networkDialog->enet->freep;
1262  for(i=0;i < networkDialog->enet->nneurons;i++)
1263  {
1264  if (networkDialog->enet->neurongain[i] == 1)
1265  p++;
1266  }
1267  for(i=0;i < networkDialog->enet->nneurons;i++)
1268  {
1269  if (networkDialog->enet->neuronbias[i] == 1)
1270  {
1271  networkDialog->biases[i] = *p;
1272  p++;
1273  }
1274  }
1275  // draw connections
1276  for (i=0; i < networkDialog->enet->net_nblocks; i++)
1277  {
1278  if (networkDialog->enet->net_block[i][0] == 0)
1279  for (t=networkDialog->enet->net_block[i][1]; t < (networkDialog->enet->net_block[i][1] + networkDialog->enet->net_block[i][2]); t++)
1280  for (b=networkDialog->enet->net_block[i][3]; b < (networkDialog->enet->net_block[i][3] + networkDialog->enet->net_block[i][4]); b++)
1281  {
1282 
1283  if (networkDialog->getcblock() == i)
1284  wid = 2;
1285  else
1286  wid = 1;
1287  w = *p;
1288  if (w != networkDialog->enet->DEFAULT_VALUE)
1289  {
1290  if (w > networkDialog->enet->wrange)
1291  w = networkDialog->enet->wrange;
1292  if (w < (0.0 - networkDialog->enet->wrange))
1293  w = 0.0 - networkDialog->enet->wrange;
1294  cr = cg = cb = 255;
1295  if (w > 0)
1296  {
1297  cg -= ((w / networkDialog->enet->wrange) * 255);
1298  cb -= ((w / networkDialog->enet->wrange) * 255);
1299  }
1300  else
1301  {
1302  cg += ((w / networkDialog->enet->wrange) * 255);
1303  cr += ((w / networkDialog->enet->wrange) * 255);
1304  }
1305  }
1306  else
1307  {
1308  cr=0;
1309  cg=185;
1310  cb=0;
1311  }
1312 
1313  painter.setPen(QPen(QColor(cr,cg,cb,255), wid, Qt::SolidLine));
1314  p++;
1315  if (abs(networkDialog->enet->neuronxy[b][1] - networkDialog->enet->neuronxy[t][1]) > 20)
1316  painter.drawLine((float) networkDialog->enet->neuronxy[t][0], (float) networkDialog->enet->neuronxy[t][1], (float) networkDialog->enet->neuronxy[b][0], (float) networkDialog->enet->neuronxy[b][1]);
1317  else
1318  {
1319  dx = abs(networkDialog->enet->neuronxy[t][0] - networkDialog->enet->neuronxy[b][0]);
1320  dy = abs(networkDialog->enet->neuronxy[t][1] - networkDialog->enet->neuronxy[b][1]);
1321  if (networkDialog->enet->neuronxy[t][0] < networkDialog->enet->neuronxy[b][0])
1322  sx = networkDialog->enet->neuronxy[t][0];
1323  else
1324  sx = networkDialog->enet->neuronxy[b][0];
1325  if (networkDialog->enet->neuronxy[t][1] < networkDialog->enet->neuronxy[b][1])
1326  sy = networkDialog->enet->neuronxy[t][1];
1327  else
1328  sy = networkDialog->enet->neuronxy[b][1];
1329  painter.drawArc((float) sx,(float) (sy-20),(float) dx, (float) (dy+40), 0 * 16, 180 * 16);
1330  }
1331  }
1332  // skip timeconstant of update blocks and store neurons of the selected block
1333  if (networkDialog->enet->net_block[i][0] == 1)
1334  {
1335  if (networkDialog->getcblock() == i)
1336  {
1337  selectedneurons[0] = networkDialog->enet->net_block[i][1];
1338  selectedneurons[1] = networkDialog->enet->net_block[i][2];
1339  }
1340  for(t=networkDialog->enet->net_block[i][1]; t < (networkDialog->enet->net_block[i][1] + networkDialog->enet->net_block[i][2]); t++)
1341  if (networkDialog->enet->neurontype[t] == 1)
1342  p++;
1343  }
1344  }
1345  // draw neurons
1346  for (i=0; i < networkDialog->enet->nneurons; i++)
1347  {
1348  if (networkDialog->enet->neuronbias[i] == 1)
1349  {
1350  w = networkDialog->biases[i];
1351  if (w != networkDialog->enet->DEFAULT_VALUE)
1352  {
1353  if (w > networkDialog->enet->wrange)
1354  w = networkDialog->enet->wrange;
1355  if (w < (0.0 - networkDialog->enet->wrange))
1356  w = 0.0 - networkDialog->enet->wrange;
1357  cr = cg = cb = 255;
1358  if (w > 0)
1359  {
1360  cg -= ((w / networkDialog->enet->wrange) * 255);
1361  cb -= ((w / networkDialog->enet->wrange) * 255);
1362  }
1363  else
1364  {
1365  cg += ((w / networkDialog->enet->wrange) * 255);
1366  cr += ((w / networkDialog->enet->wrange) * 255);
1367  }
1368  }
1369  else
1370  {
1371  cr = 0;
1372  cg = 185;
1373  cb = 0;
1374  }
1375  wid = 2;
1376  if (i >= selectedneurons[0] && i < selectedneurons[0]+selectedneurons[1])
1377  wid = 4;
1378  painter.setPen(QPen(QColor(cr,cg,cb,255), wid, Qt::SolidLine));
1379  }
1380  else
1381  {
1382  wid = 1;
1383  if (i >= selectedneurons[0] && i < selectedneurons[0]+selectedneurons[1])
1384  wid = 4;
1385  painter.setPen(QPen(Qt::black, wid, Qt::SolidLine));
1386  }
1387 
1388  if (networkDialog->enet->neurontype[i] == 0)
1389  painter.setBrush(QBrush(QColor(75, 75, 75, 255), Qt::SolidPattern)); // standard logistic in dark-gray
1390  else
1391  if (networkDialog->enet->neurontype[i] == 1)
1392  painter.setBrush(QBrush(QColor(255, 0, 0, 255), Qt::SolidPattern)); // dynamic with timeconstant in red
1393  else
1394  if (networkDialog->enet->neurontype[i] == 2)
1395  painter.setBrush(QBrush(QColor(0, 0, 255, 255), Qt::SolidPattern)); // binary in blue
1396  else
1397  painter.setBrush(QBrush(QColor(150, 150, 150, 255), Qt::SolidPattern)); // logistic 20% in light-gray
1398 
1399  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 5), 10.0, 10.0);
1400 
1401  // for neurons with gain parameters we display an additional white point in the centre of the circle
1402  if (networkDialog->enet->neurongain[i] == 1)
1403  {
1404  painter.setPen(QPen(QColor(255,255,255,255), wid, Qt::SolidLine));
1405  painter.setBrush(QBrush(QColor(255, 255, 255, 255), Qt::SolidPattern));
1406  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 1), (float) (networkDialog->enet->neuronxy[i][1] - 1), 2.0, 2.0);
1407  }
1408 
1409  }
1410 
1411  painter.setPen(Qt::black);
1412  for (i=0; i < networkDialog->enet->nneurons; i++)
1413  {
1414  if (networkDialog->enet->neurondisplay[i] == 1)
1415  painter.setPen(Qt::black);
1416  else
1417  painter.setPen(Qt::red);
1418  if (i < networkDialog->ninputs)
1419  labelxy.setRect((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] + 5), 30, 30);
1420  else
1421  labelxy.setRect((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 18), 30, 30);
1422  painter.drawText(labelxy, networkDialog->neuroncl[i]);
1423 
1424  painter.setPen(Qt::darkRed);
1425  if (networkDialog->enet->neuronlesion[i]) painter.drawText(networkDialog->enet->neuronxy[i][0]-5,networkDialog->enet->neuronxy[i][1]-5,"X");//onofrio
1426  }
1427 
1428  painter.setBrush(Qt::black);
1429  if (networkDialog->cneuronn == 1)
1430  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][1] - 5), 10.0, 10.0);
1431  if (networkDialog->cneuronn >= 2)
1432  {
1433  if (networkDialog->cneuron[0] <= networkDialog->cneuron[1])
1434  {
1435  for (i=networkDialog->cneuron[0]; i <= networkDialog->cneuron[1]; i++)
1436  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 5), 10.0, 10.0);
1437  }
1438  else
1439  {
1440  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][1] - 5), 10.0, 10.0);
1441  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[1]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[1]][1] - 5), 10.0, 10.0);
1442  }
1443  }
1444  painter.setBrush(Qt::blue);
1445  if (networkDialog->cneuronn == 3)
1446  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[2]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[2]][1] - 5), 10.0, 10.0);
1447  if (networkDialog->cneuronn == 4 && networkDialog->cneuron[2] <= networkDialog->cneuron[3])
1448  for (i=networkDialog->cneuron[2]; i <= networkDialog->cneuron[3]; i++)
1449  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 5), 10.0, 10.0);
1450 
1451 
1452 
1453 }
1454 
1455 
1456 /*
1457  * handle mouse buttons
1458  */
1459 void
1460 RendNetwork::mousePressEvent(QMouseEvent *event)
1461 {
1462 
1463  int x,y,b;
1464  int i,t;
1465  int mode;
1466  double cdist, dist;
1467 
1468  x=event->x();
1469  y=event->y();
1470  b=event->button();
1471 
1472 
1473  if (b == 2)
1474  {
1475  // right button has been pressed
1476  }
1477  else
1478  {
1479  // left button
1480  if (b == 1)
1481  {
1482  mode = 0;
1483  rnmousex = x;
1484  rnmousey = y;
1485 
1486  // on a neuron: select the neuron (up to 4)
1487  if (mode == 0)
1488  for(i=0; i < networkDialog->enet->nneurons; i++)
1489  {
1490  if (mdist((float) x,(float) y, (float) networkDialog->enet->neuronxy[i][0] * networkDialog->cscalex, (float) networkDialog->enet->neuronxy[i][1] * networkDialog->cscaley) < 10.0)
1491  {
1492  if (networkDialog->cneuronn >= 4)
1493  networkDialog->cneuronn = 0;
1494  networkDialog->cneuron[networkDialog->cneuronn] = i;
1495  networkDialog->cneuronn++;
1496  mode = 2;
1497  networkDialog->statusb->setText(QString("%1 neurons selected").arg(networkDialog->cneuronn));
1498  emit selectedneuronsChanged();
1499  }
1500  }
1501  // on a connection: select the receiving and sending neuron
1502  if (mode == 0)
1503  {
1504  dist = 999.99;
1505  for (i=0; i < networkDialog->enet->net_nblocks; i++)
1506  {
1507  if (networkDialog->enet->net_block[i][0] == 0)
1508  for (t=networkDialog->enet->net_block[i][1]; t < (networkDialog->enet->net_block[i][1] + networkDialog->enet->net_block[i][2]); t++)
1509  for (b=networkDialog->enet->net_block[i][3]; b < (networkDialog->enet->net_block[i][3] + networkDialog->enet->net_block[i][4]); b++)
1510  {
1511  cdist = segmentdist((float) x, (float) y, (float) networkDialog->enet->neuronxy[t][0] * networkDialog->cscalex, (float) networkDialog->enet->neuronxy[t][1] * networkDialog->cscaley, (float) networkDialog->enet->neuronxy[b][0] * networkDialog->cscalex, (float) networkDialog->enet->neuronxy[b][1] * networkDialog->cscaley);
1512  {
1513  if (cdist < 1 && cdist < dist)
1514  {
1515  dist = cdist;
1516  networkDialog->cneuron[0] = t;
1517  networkDialog->cneuron[1] = t;
1518  networkDialog->cneuron[2] = b;
1519  networkDialog->cneuron[3] = b;
1520  networkDialog->cneuronn = 4;
1521  networkDialog->statusb->setText(QString("A single connection have been selected"));
1522  mode = 1;
1523  }
1524  }
1525  }
1526  }
1527  }
1528  // otherwise remove selected neurons
1529  // and reset the display modality to label
1530  if (mode == 0)
1531  {
1532  networkDialog->cneuronn = 0;
1533  networkDialog->pseudomode = 0;
1534  networkDialog->pseudo_activate_net();
1535  networkDialog->statusb->setText(QString("0 selected neurons"));
1536  emit selectedneuronsChanged();
1537  }
1538  update();
1539  }
1540  }
1541 
1542 
1543 
1544 }
1545 
1546 
1547 /*
1548  * handle mouse move events
1549  */
1550 void
1551 RendNetwork::mouseMoveEvent(QMouseEvent *event)
1552 {
1553 
1554  int x,y;
1555  int i;
1556  int mode;
1557  QPoint xy;
1558  int cn;
1559 
1560 
1561  x=event->x();
1562  y=event->y();
1563 
1564  mode = 0;
1565 
1566  // move current neuron
1567  networkDialog->cneuronn = 0;
1568  if (mode == 0)
1569  {
1570  for(i=0, cn=-1; i < networkDialog->enet->nneurons; i++)
1571  if (mdist((float) rnmousex,(float) rnmousey, (float) networkDialog->enet->neuronxy[i][0] * networkDialog->cscalex, (float) networkDialog->enet->neuronxy[i][1] * networkDialog->cscaley) < 10.0)
1572  cn = i;
1573  if (cn >= 0)
1574  {
1575  networkDialog->enet->neuronxy[cn][0] = (float) x / networkDialog->cscalex;
1576  networkDialog->enet->neuronxy[cn][1] = (float) y / networkDialog->cscaley;
1577  update();
1578  rnmousex = x;
1579  rnmousey = y;
1580  mode = 1;
1581  networkDialog->statusb->setText(QString("neuron position modified"));
1582 
1583  //sprintf(sbuffer,"neuron #%d moved to %d %d", cn, enet->neuronxy[cn][0], enet->neuronxy[cn][1]);
1584  //display_stat_message(sbuffer);
1585  }
1586  }
1587 
1588 }
1589 
1590 
1591 /*
1592  * handle mouse release events by constraints movements to the grid (if any)
1593  */
1594 void
1595 RendNetwork::mouseReleaseEvent(QMouseEvent *event)
1596 {
1597 
1598  int i;
1599  int mode;
1600  QPoint xy;
1601  float *o = NULL;
1602  float oldp1,oldp2;
1603  int cn;
1604 
1605 
1606  if (networkDialog->grid > 0)
1607  {
1608 
1609  rnmousex=event->x();
1610  rnmousey=event->y();
1611 
1612  mode = 0;
1613 
1614  // move current neuron
1615  if (mode == 0)
1616  for(i=0, cn=-1; i < networkDialog->enet->nneurons; i++)
1617  if (mdist((float) rnmousex,(float) rnmousey, networkDialog->enet->neuronxy[i][0], networkDialog->enet->neuronxy[i][1]) < 10.0)
1618  cn = i;
1619  if (cn >= 0)
1620  {
1621  oldp1 = networkDialog->enet->neuronxy[cn][0];
1622  oldp2 = networkDialog->enet->neuronxy[cn][1];
1623  networkDialog->enet->neuronxy[cn][0] = (float) (((int) networkDialog->enet->neuronxy[cn][0]) / networkDialog->grid * networkDialog->grid);
1624  networkDialog->enet->neuronxy[cn][1] = (float) (((int) networkDialog->enet->neuronxy[cn][1]) / networkDialog->grid * networkDialog->grid);
1625  if ((oldp1 - networkDialog->enet->neuronxy[cn][0]) > (networkDialog->grid / 2))
1626  networkDialog->enet->neuronxy[cn][0] += networkDialog->grid;
1627  if ((oldp2 - networkDialog->enet->neuronxy[cn][1]) > (networkDialog->grid / 2))
1628  networkDialog->enet->neuronxy[cn][1] += networkDialog->grid;
1629  update();
1630  networkDialog->statusb->setText(QString("neuron's position modified"));
1631  //sprintf(sbuffer,"neuron #%d released to %d %d", cn, enet->neuronxy[cn][0], enet->neuronxy[cn][1]);
1632  //display_stat_message(sbuffer);
1633  mode = 1;
1634  }
1635 
1636  if (mode == 3)
1637  {
1638  oldp1 = *o;
1639  oldp2 = *(o + 1);
1640  *o = (float) (((int) *o) / networkDialog->grid * networkDialog->grid);
1641  *(o + 1) = (float) (((int) *(o + 1)) / networkDialog->grid * networkDialog->grid);
1642  if ((oldp1 - *o) > (networkDialog->grid / 2))
1643  *o += networkDialog->grid;
1644  if ((oldp2 - *(o + 1)) > (networkDialog->grid / 2))
1645  *(o + 1) += networkDialog->grid;
1646  networkDialog->statusb->setText(QString("neuron's position modified"));
1647  //sprintf(sbuffer,"object %s #%d released to %.1f %.1f", nobject, idobject, *o, *(o + 1));
1648  //display_stat_message(sbuffer);
1649  update();
1650  }
1651 
1652  }
1653 
1654 
1655 }
1656 
1657 /*
1658  * handle mouse buttons
1659  */
1660 void
1661 RendNetwork::mouseDoubleClickEvent(QMouseEvent* /*event*/)
1662 {
1663 
1664 }
1665 
1666 
1667 
1668 double
1669 RendNetwork::mdist(float x, float y, float x1, float y1)
1670 
1671 {
1672  double qdist;
1673 
1674  qdist = ((x-x1)*(x-x1)) + ((y-y1)*(y-y1));
1675  return(sqrt(qdist));
1676 }
1677 
1678 /*
1679 * estimate the distance between a point (p) and a segment (a-b)
1680 * by computing dist(p,a) + dist(p,b) - dist(a,b)
1681 * if one of the two distances are greater than the segment
1682 * assume that the point is too far or is outside the segment
1683 */
1684 double
1685 RendNetwork::segmentdist(float px,float py,float ax,float ay,float bx,float by)
1686 {
1687  double dab,dpa,dpb;
1688 
1689  dab = sqrt(((ax-bx)*(ax-bx)) + ((ay-by)*(ay-by)));
1690  dpa = sqrt(((px-ax)*(px-ax)) + ((py-ay)*(py-ay)));
1691  dpb = sqrt(((px-bx)*(px-bx)) + ((py-by)*(py-by)));
1692 
1693  if (dpa < dab && dpb < dab)
1694  return((dpa+dpb)-dab);
1695  else
1696  return(99999.999);
1697 }
1698 
1699 /* EvoSlider */
1700 EvoSlider::EvoSlider(float *ref, float rangemin , float rangemax, QWidget * parent)
1701 : QSlider(parent) {
1702  vref=ref;
1703  setRange((int)(rangemin*100),(int)(rangemax*100));
1704  setValue( (*vref)*100 );
1705  setOrientation(Qt::Vertical);
1706  connect(this,SIGNAL(valueChanged(int)),this, SLOT(updateValue(int)));
1707 }
1708 
1709 void EvoSlider::updateValue(int ival)
1710 {
1711  *vref=(float)ival/100.0;
1712  emit networkChanged();
1713 }
1714 
1715 /* Mixer */
1716 MixerDialog::MixerDialog(Evonet *enet, NetworkDialog* netd)
1717 : QWidget( netd ) {
1718  evonet=enet;
1719  netdl=netd;
1720  trialRef=0.0;
1721  layout=new QGridLayout(this);
1722 }
1723 
1724 void MixerDialog::setUpMixer()
1725 {
1726  // We don't use findChildren<QWidget*> because it finds children recursively and
1727  // could lead to double-frees. The dynamic_cast ensures that only QWidget children
1728  // are deleted
1729  foreach(QObject* child, children()) {
1730  delete dynamic_cast<QWidget*>(child);
1731  }
1732 
1733  if(evonet->neuronlesions || evonet->nselected > 0)
1734  {
1735  statusmixer = new QLabel("",this);
1736  if (netdl->pseudomode == 2)
1737  statusmixer->setText(QString("weights:"));
1738  if (netdl->pseudomode == 1)
1739  statusmixer->setText(QString("t-const:"));
1740  if (netdl->pseudomode == 3)
1741  statusmixer->setText(QString("biases:"));
1742  if (netdl->pseudomode == 4)
1743  statusmixer->setText(QString("gains:"));
1744  if (evonet->neuronlesions)
1745  statusmixer->setText(QString("neurons:"));
1746  layout->addWidget(statusmixer,0,0);
1747  Logger::info(QString("Mixer for n.%1 selected parameters\n").arg(evonet->neuronlesions+evonet->nselected));
1748  }
1749 
1750  float **gp;
1751  float *v;
1752  int l;
1753  int lt,li;
1754  int line=0;
1755 
1756  // selected parameters
1757  if (evonet->nselected > 0)
1758  {
1759  gp = evonet->selectedp;
1760  v = *gp;
1761  if (netdl->pseudomode == 2)
1762  {
1763  // weights
1764  lt = netdl->cneuron[0];
1765  li = netdl->cneuron[2];
1766  line = 0;
1767  for(int i=0;i<evonet->nselected;i++,v++,li++)
1768  {
1769  if (li > netdl->cneuron[3])
1770  {
1771  lt++;
1772  li = netdl->cneuron[2];
1773  line++;
1774  }
1775  layout->addWidget(new QLabel(evonet->neuronl[lt],this),1,i);
1776  EvoSlider* slide = new EvoSlider(v,(0 - evonet->getWrange()),evonet->getWrange(),this);
1777  connect( slide, SIGNAL(networkChanged()), netdl->rendNetwork, SLOT(update()) );
1778  layout->addWidget(slide,2,i);
1779  layout->addWidget(new QLabel(evonet->neuronl[li],this),3,i);
1780  }
1781  }
1782  else
1783  {
1784  // timeconstant(1), bias (2), gain(3)
1785  l = netdl->cneuron[0];
1786  for(int i=0;i<evonet->nselected;i++,v++,l++)
1787  {
1788  layout->addWidget(new QLabel(evonet->neuronl[l],this),1,i);
1789  EvoSlider* slide = new EvoSlider(v,(0 - evonet->getWrange()),evonet->getWrange(),this);
1790  connect( slide, SIGNAL(networkChanged()), netdl->rendNetwork, SLOT(update()) );
1791  layout->addWidget(slide,2,i);
1792  }
1793  }
1794  }
1795  else
1796  {
1797  // state of lesioned neurons
1798  for(int i=0;i<evonet->getNoNeurons();i++)
1799  if(evonet->neuronlesion[i])
1800  {
1801  layout->addWidget(new QLabel(evonet->neuronl[i],this),1,i);
1802  EvoSlider* slide = new EvoSlider(&evonet->neuronlesionVal[i],evonet->neuronrange[i][0],evonet->neuronrange[i][1],this);
1803  connect( slide, SIGNAL(networkChanged()), netdl->rendNetwork, SLOT(update()) );
1804  layout->addWidget(slide,2,i);
1805  }
1806  }
1807 
1808 }
1809 
1810 } //end namespace farsa
1811 
1812 // All the suff below is to restore the warning state on Windows
1813 #if defined(_MSC_VER)
1814  #pragma warning(pop)
1815 #endif