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 < 5; 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<5; 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  block_name(cblock, stblock);
706  cblockAct->insertItems(cblock+1, QStringList() << stblock);
707  enet->net_nblocks++;
708  cneuronn = 0;
709  }
710 
711  if (cneuronn == 2)
712  {
713  for(i=enet->net_nblocks; i > cblock; i--)
714  for(ii=0; ii<5; ii++)
715  enet->net_block[i][ii] = enet->net_block[i-1][ii];
716  enet->net_block[cblock][0] = 1;
717  enet->net_block[cblock][1] = cneuron[0];
718  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
719  enet->net_block[cblock][3] = 0;
720  enet->net_block[cblock][4] = 0;
721  block_name(cblock, stblock);
722  cblockAct->insertItems(cblock+1, QStringList() << stblock);
723  enet->net_nblocks++;
724  cneuronn = 0;
725  }
726 
727  cblockAct->setCurrentIndex(0);
728  statusb->setText(QString("Update block added"));
729  rendNetwork->update();
730 }
731 
732 
733 // Add a connection block
734 void NetworkDialog::add_cblock()
735 {
736 
737  int i,ii;
738  char stblock[1024];
739  int cblock;
740 
741 
742  if (cneuronn != 4)
743  {
744  warning("you should select the receiving and sending blocks (4 neurons) first");
745  return;
746  }
747 
748  cblock = getcblock(); // we add the new block before the selected block
749  printf("cblock %d\n", cblock);
750  if (cblock < 0)
751  cblock = enet->net_nblocks; // or we add it at the end of the block list
752 
753 
754  if (cneuronn == 4)
755  {
756  for(i=enet->net_nblocks; i > cblock; i--)
757  for(ii=0; ii<5; ii++)
758  enet->net_block[i][ii] = enet->net_block[i-1][ii];
759  enet->net_block[cblock][0] = 0;
760  enet->net_block[cblock][1] = cneuron[0];
761  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
762  enet->net_block[cblock][3] = cneuron[2];
763  enet->net_block[cblock][4] = cneuron[3] - cneuron[2] + 1;
764  block_name(cblock, stblock);
765  cblockAct->insertItems(cblock+1, QStringList() << stblock);
766  enet->net_nblocks++;
767  cneuronn = 0;
768  }
769 
770  cblockAct->setCurrentIndex(0);
771  statusb->setText(QString("Connection block added"));
772  rendNetwork->update();
773 }
774 
775 // Add a gain block
776 void NetworkDialog::add_gblock()
777 {
778 
779  int i,ii;
780  char stblock[1024];
781  int cblock;
782 
783  if (cneuronn != 2 && cneuronn != 3)
784  {
785  warning("you should select a block (2 neurons) and eventually a third neuron first");
786  return;
787  }
788 
789  cblock = getcblock(); // we add the new block before the selected block
790  if (cblock < 0)
791  cblock = enet->net_nblocks; // or we add it at the end of the block list
792 
793 
794  // 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
795  if (cneuronn == 2)
796  {
797  for(i=enet->net_nblocks; i > cblock; i--)
798  for(ii=0; ii<5; ii++)
799  enet->net_block[i][ii] = enet->net_block[i-1][ii];
800  enet->net_block[cblock][0] = 2;
801  enet->net_block[cblock][1] = cneuron[0];
802  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
803  enet->net_block[cblock][3] = 0;
804  enet->net_block[cblock][4] = 0;
805  block_name(cblock, stblock);
806  cblockAct->insertItems(cblock+1, QStringList() << stblock);
807  enet->net_nblocks++;
808  cneuronn = 0;
809  }
810  // 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
811  if (cneuronn == 3)
812  {
813  for(i=enet->net_nblocks; i > cblock; i--)
814  for(ii=0; ii<5; ii++)
815  enet->net_block[i][ii] = enet->net_block[i-1][ii];
816  enet->net_block[cblock][0] = 3;
817  enet->net_block[cblock][1] = cneuron[0];
818  enet->net_block[cblock][2] = cneuron[1] - cneuron[0] + 1;
819  enet->net_block[cblock][3] = cneuron[2];
820  enet->net_block[cblock][4] = 0;
821  block_name(cblock, stblock);
822  cblockAct->insertItems(cblock+1, QStringList() << stblock);
823  enet->net_nblocks++;
824  cneuronn = 0;
825  }
826 
827  cblockAct->setCurrentIndex(0);
828  statusb->setText(QString("Gain block added"));
829  rendNetwork->update();
830 }
831 
832 
833 /*
834  * open a .net or .phe file
835  */
836 void NetworkDialog::open()
837 {
838 
839  char *f;
840  QByteArray filen;
841  char filename[256];
842 
843 
844  QString fileName = QFileDialog::getOpenFileName(this,
845  "Choose a filename to open",
846  "",
847  "*.net *.phe");
848 
849 
850  if (fileName.endsWith("net"))
851  {
852  filen = fileName.toAscii();
853  f = filen.data();
854  strcpy(filename, f);
855  enet->load_net_blocks(filename, 0);
856  statusb->setText(QString("File %1 loaded").arg(filename));
857  }
858  else
859  if (fileName.endsWith("phe"))
860  {
861  filen = fileName.toAscii();
862  f = filen.data();
863  strcpy(filename, f);
864  enet->load_net_blocks(filename, 1);
865  statusb->setText(QString("File %1 loaded").arg(filename));
866  }
867 
868 }
869 
870 /*
871  * save a .net or .phe file
872  */
873 void NetworkDialog::save()
874 {
875 
876  char *f;
877  QByteArray filen;
878  char filename[256];
879 
880 
881  QString fileName = QFileDialog::getSaveFileName(this,
882  "Choose a filename to save",
883  "",
884  "*.net *.phe");
885 
886 
887  if (fileName.endsWith("net"))
888  {
889  filen = fileName.toAscii();
890  f = filen.data();
891  strcpy(filename, f);
892  enet->save_net_blocks(filename, 0);
893  statusb->setText(QString("File %1 saved").arg(filename));
894 
895  }
896  else
897  if (fileName.endsWith("phe"))
898  {
899  filen = fileName.toAscii();
900  f = filen.data();
901  strcpy(filename, f);
902  enet->save_net_blocks(filename, 1);
903  statusb->setText(QString("File %1 saved").arg(filename));
904  }
905 
906 }
907 
908 // Increase a selected value
909 void NetworkDialog::increasev()
910 {
911  float **gp;
912  float *v;
913 
914 
915  // when 2 neurons are selected we assume that the user want to change a connection weight
916  if (cneuronn == 2)
917  {
918  pseudomode = 2;
919  pseudo_activate_net();
920  if (enet->nselected == 1)
921  {
922  gp = enet->selectedp;
923  v = *gp;
924  *v += ((enet->wrange * 2.0f) / 256.0f);
925  pseudo_activate_net();
926  rendNetwork->update();
927  }
928  }
929  // when 1 neuron is selected we modify the bias of the neuron,
930  // or the delta or the gain of the neuron (if the user previously pushed the delta or gain buttons, respectively)
931  if (cneuronn == 1)
932  {
933  if (pseudomode != 1 && pseudomode != 4)
934  pseudomode = 3;
935  pseudo_activate_net();
936  if (enet->nselected == 1)
937  {
938  gp = enet->selectedp;
939  v = *gp;
940  *v += ((enet->wrange * 2.0f) / 256.0f);
941  pseudo_activate_net();
942  rendNetwork->update();
943  }
944  }
945 
946 }
947 
948 // Decrease a selected value
949 void NetworkDialog::decreasev()
950 {
951 
952  float **gp;
953  float *v;
954 
955 
956  // when 2 neurons are selected we assume that the user want to change a connection weight
957  if (cneuronn == 2)
958  {
959  pseudomode = 2;
960  pseudo_activate_net();
961  if (enet->nselected == 1)
962  {
963  gp = enet->selectedp;
964  v = *gp;
965  *v -= ((enet->wrange * 2.0f) / 256.0f);
966  pseudo_activate_net();
967  rendNetwork->update();
968  }
969  }
970  // when 1 neuron is selected we modify the bias of the neuron,
971  // or the delta or the gain of the neuron (if the user previously pushed the delta or gain buttons, respectively)
972  if (cneuronn == 1)
973  {
974  if (pseudomode != 1 && pseudomode != 4)
975  pseudomode = 3;
976  pseudo_activate_net();
977  if (enet->nselected == 1)
978  {
979  gp = enet->selectedp;
980  v = *gp;
981  *v -= ((enet->wrange * 2.0f) / 256.0f);
982  pseudo_activate_net();
983  rendNetwork->update();
984  }
985  }
986 
987 }
988 
989 // It return the name/description of an existing block
990 void NetworkDialog::block_name(int b, char *st)
991 {
992  switch(enet->net_block[b][0])
993  {
994  case 0:
995  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]);
996  break;
997  case 1:
998  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]);
999  break;
1000  case 2:
1001  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]);
1002  break;
1003  case 3:
1004  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]]);
1005  break;
1006  default:
1007  sprintf(st,"undefined block type");
1008  break;
1009  }
1010 
1011 }
1012 
1013 /*
1014  * This function replace the current neuron labels string with the user's selected parameter:
1015  * (timeconstant, weight, bias, gain). Selected parameters are also stored in the selectedp
1016  * pointer list.
1017  */
1018 void
1019 NetworkDialog::pseudo_activate_net()
1020 
1021 {
1022  int i;
1023  int t;
1024  int b;
1025  float delta;
1026  float gain;
1027  float bias;
1028  float **gp;
1029  int ddelta=0;
1030  int dweight=0;
1031  int dbias=0;
1032  int dgain=0;
1033  float *p;
1034 
1035  switch(pseudomode)
1036  {
1037  case 1:
1038  ddelta = 1;
1039  break;
1040  case 2:
1041  dweight = 1;
1042  break;
1043  case 3:
1044  dbias = 1;
1045  break;
1046  case 4:
1047  dgain = 1;
1048  break;
1049  }
1050 
1051  p = freep;
1052  gp = enet->selectedp;
1053  enet->nselected = 0;
1054 
1055  for(i=0;i < enet->nneurons;i++)
1056  strcpy(neuroncl[i],enet->neuronl[i]);
1057 
1058  //for(i=0;i < enet->nneurons;i++)
1059  // updated[i] = 0;
1060 
1061  // gain (from the first to the second selected neuron)
1062  for(i=0;i < enet->nneurons;i++)
1063  {
1064  if (enet->neurongain[i] == 1)
1065  {
1066  if (dgain > 0 && ((cneuronn == 1 && i == cneuron[0]) || (cneuronn == 2 && i >= cneuron[0] && i <= cneuron[1])))
1067  {
1068  gain = (fabs((double) *p) / enet->wrange) * enet->grange;
1069  sprintf(neuroncl[i],"%.1f",gain);
1070  *gp = p;
1071  gp++;
1072  enet->nselected++;
1073  }
1074  p++;
1075  }
1076  }
1077 
1078  // biases (from the first to the second selected neuron)
1079  for(i=0;i < enet->nneurons;i++)
1080  {
1081  if (enet->neuronbias[i] == 1)
1082  {
1083  if (dbias > 0 && ((cneuronn == 1 && i == cneuron[0]) || (cneuronn == 2 && i >= cneuron[0] && i <= cneuron[1])))
1084  {
1085  bias = (fabs((double) *p) / enet->wrange) * enet->brange;
1086  sprintf(neuroncl[i],"%.1f",bias);
1087  *gp = p;
1088  gp++;
1089  enet->nselected++;
1090  }
1091  p++;
1092  }
1093  }
1094 
1095  // blocks
1096  for (b=0; b < enet->net_nblocks; b++)
1097  {
1098  // connection block
1099  if (enet->net_block[b][0] == 0)
1100  {
1101  for(t=enet->net_block[b][1]; t < enet->net_block[b][1] + enet->net_block[b][2];t++)
1102  for(i=enet->net_block[b][3]; i < enet->net_block[b][3] + enet->net_block[b][4];i++)
1103  {
1104  // weights (4 neurons, receiving block, sending block)
1105  if (dweight == 1 && cneuronn == 4 && (t >= cneuron[0] && t <= cneuron[1]) && (i >= cneuron[2] && i <= cneuron[3]))
1106  {
1107  // values can be visualized in the label only if a single receiving neuron has been selected
1108  if (cneuron[0] == cneuron[1])
1109  sprintf(neuroncl[i],"%.1f",*p);
1110  *gp = p;
1111  gp++;
1112  enet->nselected++;
1113  }
1114  p++;
1115  }
1116  }
1117  // update block
1118  if (enet->net_block[b][0] == 1)
1119  {
1120  for(t=enet->net_block[b][1]; t < (enet->net_block[b][1] + enet->net_block[b][2]); t++)
1121  {
1122  //updated[t] +=1;
1123  if (enet->neurontype[t] != 1)
1124  {
1125  ;
1126  }
1127  else
1128  {
1129  // timeconstant (from the first to the second selected neuron)
1130  delta = (float) (fabs((double) *p) / enet->wrange);
1131  if (ddelta > 0 && ((cneuronn == 1 && t == cneuron[0]) || (cneuronn == 2 && t >= cneuron[0] && t <= cneuron[1])))
1132  {
1133  sprintf(neuroncl[t],"%.1f",delta);
1134  *gp = p;
1135  gp++;
1136  enet->nselected++;
1137  }
1138  p++;
1139  }
1140  }
1141  }
1142  }
1143 
1144 
1145 }
1146 
1147 /*
1148  * Mixer for lesioned or freezed neurons
1149  */
1150 void NetworkDialog::openMixer()
1151 {
1152 
1153  //mixerDialog=new MixerDialog(this->enet, this);
1154  mixerDialog->setUpMixer();
1155  mixerDialog->show();
1156  rendNetwork->update();
1157 
1158 }
1159 
1160 
1161 
1162 // -----------------------------------------------------
1163 // Widget RendNetwork
1164 // -----------------------------------------------------
1165 
1166 RendNetwork::RendNetwork( NetworkDialog* networkDialog, QWidget *parent)
1167  : QWidget(parent)
1168 {
1169  shape = Polygon;
1170  antialiased = false;
1171  pixmap.load(":/evorobot/qt-logo.png");
1172 
1173  setBackgroundRole(QPalette::Base);
1174  this->networkDialog = networkDialog;
1175 
1176  rnmousex = 20000;
1177  rnmousey = 30000;
1178 }
1179 
1180 QSize RendNetwork::minimumSizeHint() const
1181 {
1182  return QSize(250, 250);
1183 }
1184 
1185 QSize RendNetwork::sizeHint() const
1186 {
1187  return QSize(550, 500);
1188 }
1189 
1190 void RendNetwork::setShape(Shape shape)
1191 {
1192  this->shape = shape;
1193  update();
1194 }
1195 
1196 void RendNetwork::setPen(const QPen &pen)
1197 {
1198  this->pen = pen;
1199  update();
1200 }
1201 
1202 
1203 
1204 void RendNetwork::setBrush(const QBrush &brush)
1205 {
1206  this->brush = brush;
1207  update();
1208 }
1209 
1210 void RendNetwork::setAntialiased(bool antialiased)
1211 {
1212  this->antialiased = antialiased;
1213  update();
1214 }
1215 
1216 void RendNetwork::setTransformed(bool transformed)
1217 {
1218  this->transformed = transformed;
1219  update();
1220 }
1221 
1222 
1223 void RendNetwork::paintEvent(QPaintEvent *)
1224 {
1225 
1226 
1227  int i;
1228  int t,b;
1229  int sx,sy,dx,dy;
1230  float *p;
1231  int cr,cb,cg;
1232  int wid = 1;
1233  float w;
1234  int selectedneurons[2];
1235  QPainter painter(this);
1236 
1237  QRect labelxy(0,0,30,20); // neuron labels
1238  QPoint pxy;
1239  painter.setPen(pen);
1240  QPen pen(Qt::black, 1); // black solid line, 1 pixels wide
1241  painter.setPen(pen);
1242  selectedneurons[0] = selectedneurons[1] = -1;
1243  // set the scale
1244  if (networkDialog->enet->drawnxmax > 0 && networkDialog->enet->drawnymax > 0)
1245  {
1246  networkDialog->cscaley = height() / (float) networkDialog->enet->drawnymax;
1247  networkDialog->cscalex = width() / (float) networkDialog->enet->drawnxmax;
1248  painter.scale(networkDialog->cscalex, networkDialog->cscaley);
1249  }
1250  else
1251  {
1252  painter.scale(1.0,1.0);
1253  }
1254  painter.setPen(Qt::gray);
1255  // extract gain and biases
1256  p = networkDialog->enet->freep;
1257  for(i=0;i < networkDialog->enet->nneurons;i++)
1258  {
1259  if (networkDialog->enet->neurongain[i] == 1)
1260  p++;
1261  }
1262  for(i=0;i < networkDialog->enet->nneurons;i++)
1263  {
1264  if (networkDialog->enet->neuronbias[i] == 1)
1265  {
1266  networkDialog->biases[i] = *p;
1267  p++;
1268  }
1269  }
1270  // draw connections
1271  for (i=0; i < networkDialog->enet->net_nblocks; i++)
1272  {
1273  if (networkDialog->enet->net_block[i][0] == 0)
1274  for (t=networkDialog->enet->net_block[i][1]; t < (networkDialog->enet->net_block[i][1] + networkDialog->enet->net_block[i][2]); t++)
1275  for (b=networkDialog->enet->net_block[i][3]; b < (networkDialog->enet->net_block[i][3] + networkDialog->enet->net_block[i][4]); b++)
1276  {
1277 
1278  if (networkDialog->getcblock() == i)
1279  wid = 2;
1280  else
1281  wid = 1;
1282  w = *p;
1283  if (w != networkDialog->enet->DEFAULT_VALUE)
1284  {
1285  if (w > networkDialog->enet->wrange)
1286  w = networkDialog->enet->wrange;
1287  if (w < (0.0 - networkDialog->enet->wrange))
1288  w = 0.0 - networkDialog->enet->wrange;
1289  cr = cg = cb = 255;
1290  if (w > 0)
1291  {
1292  cg -= ((w / networkDialog->enet->wrange) * 255);
1293  cb -= ((w / networkDialog->enet->wrange) * 255);
1294  }
1295  else
1296  {
1297  cg += ((w / networkDialog->enet->wrange) * 255);
1298  cr += ((w / networkDialog->enet->wrange) * 255);
1299  }
1300  }
1301  else
1302  {
1303  cr=0;
1304  cg=185;
1305  cb=0;
1306  }
1307 
1308  painter.setPen(QPen(QColor(cr,cg,cb,255), wid, Qt::SolidLine));
1309  p++;
1310  if (abs(networkDialog->enet->neuronxy[b][1] - networkDialog->enet->neuronxy[t][1]) > 20)
1311  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]);
1312  else
1313  {
1314  dx = abs(networkDialog->enet->neuronxy[t][0] - networkDialog->enet->neuronxy[b][0]);
1315  dy = abs(networkDialog->enet->neuronxy[t][1] - networkDialog->enet->neuronxy[b][1]);
1316  if (networkDialog->enet->neuronxy[t][0] < networkDialog->enet->neuronxy[b][0])
1317  sx = networkDialog->enet->neuronxy[t][0];
1318  else
1319  sx = networkDialog->enet->neuronxy[b][0];
1320  if (networkDialog->enet->neuronxy[t][1] < networkDialog->enet->neuronxy[b][1])
1321  sy = networkDialog->enet->neuronxy[t][1];
1322  else
1323  sy = networkDialog->enet->neuronxy[b][1];
1324  painter.drawArc((float) sx,(float) (sy-20),(float) dx, (float) (dy+40), 0 * 16, 180 * 16);
1325  }
1326  }
1327  // skip timeconstant of update blocks and store neurons of the selected block
1328  if (networkDialog->enet->net_block[i][0] == 1)
1329  {
1330  if (networkDialog->getcblock() == i)
1331  {
1332  selectedneurons[0] = networkDialog->enet->net_block[i][1];
1333  selectedneurons[1] = networkDialog->enet->net_block[i][2];
1334  }
1335  for(t=networkDialog->enet->net_block[i][1]; t < (networkDialog->enet->net_block[i][1] + networkDialog->enet->net_block[i][2]); t++)
1336  if (networkDialog->enet->neurontype[t] == 1)
1337  p++;
1338  }
1339  }
1340  // draw neurons
1341  for (i=0; i < networkDialog->enet->nneurons; i++)
1342  {
1343  if (networkDialog->enet->neuronbias[i] == 1)
1344  {
1345  w = networkDialog->biases[i];
1346  if (w != networkDialog->enet->DEFAULT_VALUE)
1347  {
1348  if (w > networkDialog->enet->wrange)
1349  w = networkDialog->enet->wrange;
1350  if (w < (0.0 - networkDialog->enet->wrange))
1351  w = 0.0 - networkDialog->enet->wrange;
1352  cr = cg = cb = 255;
1353  if (w > 0)
1354  {
1355  cg -= ((w / networkDialog->enet->wrange) * 255);
1356  cb -= ((w / networkDialog->enet->wrange) * 255);
1357  }
1358  else
1359  {
1360  cg += ((w / networkDialog->enet->wrange) * 255);
1361  cr += ((w / networkDialog->enet->wrange) * 255);
1362  }
1363  }
1364  else
1365  {
1366  cr = 0;
1367  cg = 185;
1368  cb = 0;
1369  }
1370  wid = 2;
1371  if (i >= selectedneurons[0] && i < selectedneurons[0]+selectedneurons[1])
1372  wid = 4;
1373  painter.setPen(QPen(QColor(cr,cg,cb,255), wid, Qt::SolidLine));
1374  }
1375  else
1376  {
1377  wid = 1;
1378  if (i >= selectedneurons[0] && i < selectedneurons[0]+selectedneurons[1])
1379  wid = 4;
1380  painter.setPen(QPen(Qt::black, wid, Qt::SolidLine));
1381  }
1382 
1383  if (networkDialog->enet->neurontype[i] == 0)
1384  painter.setBrush(QBrush(QColor(75, 75, 75, 255), Qt::SolidPattern)); // standard logistic in dark-gray
1385  else
1386  if (networkDialog->enet->neurontype[i] == 1)
1387  painter.setBrush(QBrush(QColor(255, 0, 0, 255), Qt::SolidPattern)); // dynamic with timeconstant in red
1388  else
1389  if (networkDialog->enet->neurontype[i] == 2)
1390  painter.setBrush(QBrush(QColor(0, 0, 255, 255), Qt::SolidPattern)); // binary in blue
1391  else
1392  painter.setBrush(QBrush(QColor(150, 150, 150, 255), Qt::SolidPattern)); // logistic 20% in light-gray
1393 
1394  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 5), 10.0, 10.0);
1395 
1396  // for neurons with gain parameters we display an additional white point in the centre of the circle
1397  if (networkDialog->enet->neurongain[i] == 1)
1398  {
1399  painter.setPen(QPen(QColor(255,255,255,255), wid, Qt::SolidLine));
1400  painter.setBrush(QBrush(QColor(255, 255, 255, 255), Qt::SolidPattern));
1401  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 1), (float) (networkDialog->enet->neuronxy[i][1] - 1), 2.0, 2.0);
1402  }
1403 
1404  }
1405 
1406  painter.setPen(Qt::black);
1407  for (i=0; i < networkDialog->enet->nneurons; i++)
1408  {
1409  if (networkDialog->enet->neurondisplay[i] == 1)
1410  painter.setPen(Qt::black);
1411  else
1412  painter.setPen(Qt::red);
1413  if (i < networkDialog->ninputs)
1414  labelxy.setRect((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] + 5), 30, 30);
1415  else
1416  labelxy.setRect((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 18), 30, 30);
1417  painter.drawText(labelxy, networkDialog->neuroncl[i]);
1418 
1419  painter.setPen(Qt::darkRed);
1420  if (networkDialog->enet->neuronlesion[i]) painter.drawText(networkDialog->enet->neuronxy[i][0]-5,networkDialog->enet->neuronxy[i][1]-5,"X");//onofrio
1421  }
1422 
1423  painter.setBrush(Qt::black);
1424  if (networkDialog->cneuronn == 1)
1425  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][1] - 5), 10.0, 10.0);
1426  if (networkDialog->cneuronn >= 2)
1427  {
1428  if (networkDialog->cneuron[0] <= networkDialog->cneuron[1])
1429  {
1430  for (i=networkDialog->cneuron[0]; i <= networkDialog->cneuron[1]; i++)
1431  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 5), 10.0, 10.0);
1432  }
1433  else
1434  {
1435  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[0]][1] - 5), 10.0, 10.0);
1436  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[1]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[1]][1] - 5), 10.0, 10.0);
1437  }
1438  }
1439  painter.setBrush(Qt::blue);
1440  if (networkDialog->cneuronn == 3)
1441  painter.drawEllipse((float) (networkDialog->enet->neuronxy[networkDialog->cneuron[2]][0] - 5), (float) (networkDialog->enet->neuronxy[networkDialog->cneuron[2]][1] - 5), 10.0, 10.0);
1442  if (networkDialog->cneuronn == 4 && networkDialog->cneuron[2] <= networkDialog->cneuron[3])
1443  for (i=networkDialog->cneuron[2]; i <= networkDialog->cneuron[3]; i++)
1444  painter.drawEllipse((float) (networkDialog->enet->neuronxy[i][0] - 5), (float) (networkDialog->enet->neuronxy[i][1] - 5), 10.0, 10.0);
1445 
1446 
1447 
1448 }
1449 
1450 
1451 /*
1452  * handle mouse buttons
1453  */
1454 void
1455 RendNetwork::mousePressEvent(QMouseEvent *event)
1456 {
1457 
1458  int x,y,b;
1459  int i,t;
1460  int mode;
1461  double cdist, dist;
1462 
1463  x=event->x();
1464  y=event->y();
1465  b=event->button();
1466 
1467 
1468  if (b == 2)
1469  {
1470  // right button has been pressed
1471  }
1472  else
1473  {
1474  // left button
1475  if (b == 1)
1476  {
1477  mode = 0;
1478  rnmousex = x;
1479  rnmousey = y;
1480 
1481  // on a neuron: select the neuron (up to 4)
1482  if (mode == 0)
1483  for(i=0; i < networkDialog->enet->nneurons; i++)
1484  {
1485  if (mdist((float) x,(float) y, (float) networkDialog->enet->neuronxy[i][0] * networkDialog->cscalex, (float) networkDialog->enet->neuronxy[i][1] * networkDialog->cscaley) < 10.0)
1486  {
1487  if (networkDialog->cneuronn >= 4)
1488  networkDialog->cneuronn = 0;
1489  networkDialog->cneuron[networkDialog->cneuronn] = i;
1490  networkDialog->cneuronn++;
1491  mode = 2;
1492  networkDialog->statusb->setText(QString("%1 neurons selected").arg(networkDialog->cneuronn));
1493  emit selectedneuronsChanged();
1494  }
1495  }
1496  // on a connection: select the receiving and sending neuron
1497  if (mode == 0)
1498  {
1499  dist = 999.99;
1500  for (i=0; i < networkDialog->enet->net_nblocks; i++)
1501  {
1502  if (networkDialog->enet->net_block[i][0] == 0)
1503  for (t=networkDialog->enet->net_block[i][1]; t < (networkDialog->enet->net_block[i][1] + networkDialog->enet->net_block[i][2]); t++)
1504  for (b=networkDialog->enet->net_block[i][3]; b < (networkDialog->enet->net_block[i][3] + networkDialog->enet->net_block[i][4]); b++)
1505  {
1506  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);
1507  {
1508  if (cdist < 1 && cdist < dist)
1509  {
1510  dist = cdist;
1511  networkDialog->cneuron[0] = t;
1512  networkDialog->cneuron[1] = t;
1513  networkDialog->cneuron[2] = b;
1514  networkDialog->cneuron[3] = b;
1515  networkDialog->cneuronn = 4;
1516  networkDialog->statusb->setText(QString("A single connection have been selected"));
1517  mode = 1;
1518  }
1519  }
1520  }
1521  }
1522  }
1523  // otherwise remove selected neurons
1524  // and reset the display modality to label
1525  if (mode == 0)
1526  {
1527  networkDialog->cneuronn = 0;
1528  networkDialog->pseudomode = 0;
1529  networkDialog->pseudo_activate_net();
1530  networkDialog->statusb->setText(QString("0 selected neurons"));
1531  emit selectedneuronsChanged();
1532  }
1533  update();
1534  }
1535  }
1536 
1537 
1538 
1539 }
1540 
1541 
1542 /*
1543  * handle mouse move events
1544  */
1545 void
1546 RendNetwork::mouseMoveEvent(QMouseEvent *event)
1547 {
1548 
1549  int x,y;
1550  int i;
1551  int mode;
1552  QPoint xy;
1553  int cn;
1554 
1555 
1556  x=event->x();
1557  y=event->y();
1558 
1559  mode = 0;
1560 
1561  // move current neuron
1562  networkDialog->cneuronn = 0;
1563  if (mode == 0)
1564  {
1565  for(i=0, cn=-1; i < networkDialog->enet->nneurons; i++)
1566  if (mdist((float) rnmousex,(float) rnmousey, (float) networkDialog->enet->neuronxy[i][0] * networkDialog->cscalex, (float) networkDialog->enet->neuronxy[i][1] * networkDialog->cscaley) < 10.0)
1567  cn = i;
1568  if (cn >= 0)
1569  {
1570  networkDialog->enet->neuronxy[cn][0] = (float) x / networkDialog->cscalex;
1571  networkDialog->enet->neuronxy[cn][1] = (float) y / networkDialog->cscaley;
1572  update();
1573  rnmousex = x;
1574  rnmousey = y;
1575  mode = 1;
1576  networkDialog->statusb->setText(QString("neuron position modified"));
1577 
1578  //sprintf(sbuffer,"neuron #%d moved to %d %d", cn, enet->neuronxy[cn][0], enet->neuronxy[cn][1]);
1579  //display_stat_message(sbuffer);
1580  }
1581  }
1582 
1583 }
1584 
1585 
1586 /*
1587  * handle mouse release events by constraints movements to the grid (if any)
1588  */
1589 void
1590 RendNetwork::mouseReleaseEvent(QMouseEvent *event)
1591 {
1592 
1593  int i;
1594  int mode;
1595  QPoint xy;
1596  float *o = NULL;
1597  float oldp1,oldp2;
1598  int cn;
1599 
1600 
1601  if (networkDialog->grid > 0)
1602  {
1603 
1604  rnmousex=event->x();
1605  rnmousey=event->y();
1606 
1607  mode = 0;
1608 
1609  // move current neuron
1610  if (mode == 0)
1611  for(i=0, cn=-1; i < networkDialog->enet->nneurons; i++)
1612  if (mdist((float) rnmousex,(float) rnmousey, networkDialog->enet->neuronxy[i][0], networkDialog->enet->neuronxy[i][1]) < 10.0)
1613  cn = i;
1614  if (cn >= 0)
1615  {
1616  oldp1 = networkDialog->enet->neuronxy[cn][0];
1617  oldp2 = networkDialog->enet->neuronxy[cn][1];
1618  networkDialog->enet->neuronxy[cn][0] = (float) (((int) networkDialog->enet->neuronxy[cn][0]) / networkDialog->grid * networkDialog->grid);
1619  networkDialog->enet->neuronxy[cn][1] = (float) (((int) networkDialog->enet->neuronxy[cn][1]) / networkDialog->grid * networkDialog->grid);
1620  if ((oldp1 - networkDialog->enet->neuronxy[cn][0]) > (networkDialog->grid / 2))
1621  networkDialog->enet->neuronxy[cn][0] += networkDialog->grid;
1622  if ((oldp2 - networkDialog->enet->neuronxy[cn][1]) > (networkDialog->grid / 2))
1623  networkDialog->enet->neuronxy[cn][1] += networkDialog->grid;
1624  update();
1625  networkDialog->statusb->setText(QString("neuron's position modified"));
1626  //sprintf(sbuffer,"neuron #%d released to %d %d", cn, enet->neuronxy[cn][0], enet->neuronxy[cn][1]);
1627  //display_stat_message(sbuffer);
1628  mode = 1;
1629  }
1630 
1631  if (mode == 3)
1632  {
1633  oldp1 = *o;
1634  oldp2 = *(o + 1);
1635  *o = (float) (((int) *o) / networkDialog->grid * networkDialog->grid);
1636  *(o + 1) = (float) (((int) *(o + 1)) / networkDialog->grid * networkDialog->grid);
1637  if ((oldp1 - *o) > (networkDialog->grid / 2))
1638  *o += networkDialog->grid;
1639  if ((oldp2 - *(o + 1)) > (networkDialog->grid / 2))
1640  *(o + 1) += networkDialog->grid;
1641  networkDialog->statusb->setText(QString("neuron's position modified"));
1642  //sprintf(sbuffer,"object %s #%d released to %.1f %.1f", nobject, idobject, *o, *(o + 1));
1643  //display_stat_message(sbuffer);
1644  update();
1645  }
1646 
1647  }
1648 
1649 
1650 }
1651 
1652 /*
1653  * handle mouse buttons
1654  */
1655 void
1656 RendNetwork::mouseDoubleClickEvent(QMouseEvent* /*event*/)
1657 {
1658 
1659 }
1660 
1661 
1662 
1663 double
1664 RendNetwork::mdist(float x, float y, float x1, float y1)
1665 
1666 {
1667  double qdist;
1668 
1669  qdist = ((x-x1)*(x-x1)) + ((y-y1)*(y-y1));
1670  return(sqrt(qdist));
1671 }
1672 
1673 /*
1674 * estimate the distance between a point (p) and a segment (a-b)
1675 * by computing dist(p,a) + dist(p,b) - dist(a,b)
1676 * if one of the two distances are greater than the segment
1677 * assume that the point is too far or is outside the segment
1678 */
1679 double
1680 RendNetwork::segmentdist(float px,float py,float ax,float ay,float bx,float by)
1681 {
1682  double dab,dpa,dpb;
1683 
1684  dab = sqrt(((ax-bx)*(ax-bx)) + ((ay-by)*(ay-by)));
1685  dpa = sqrt(((px-ax)*(px-ax)) + ((py-ay)*(py-ay)));
1686  dpb = sqrt(((px-bx)*(px-bx)) + ((py-by)*(py-by)));
1687 
1688  if (dpa < dab && dpb < dab)
1689  return((dpa+dpb)-dab);
1690  else
1691  return(99999.999);
1692 }
1693 
1694 /* EvoSlider */
1695 EvoSlider::EvoSlider(float *ref, float rangemin , float rangemax, QWidget * parent)
1696 : QSlider(parent) {
1697  vref=ref;
1698  setRange((int)(rangemin*100),(int)(rangemax*100));
1699  setValue( (*vref)*100 );
1700  setOrientation(Qt::Vertical);
1701  connect(this,SIGNAL(valueChanged(int)),this, SLOT(updateValue(int)));
1702 }
1703 
1704 void EvoSlider::updateValue(int ival)
1705 {
1706  *vref=(float)ival/100.0;
1707  emit networkChanged();
1708 }
1709 
1710 /* Mixer */
1711 MixerDialog::MixerDialog(Evonet *enet, NetworkDialog* netd)
1712 : QWidget( netd ) {
1713  evonet=enet;
1714  netdl=netd;
1715  trialRef=0.0;
1716  layout=new QGridLayout(this);
1717 }
1718 
1719 void MixerDialog::setUpMixer()
1720 {
1721  foreach( QWidget* object, findChildren<QWidget*>() ) {
1722  delete object;
1723  }
1724 
1725  if(evonet->neuronlesions || evonet->nselected > 0)
1726  {
1727  statusmixer = new QLabel("",this);
1728  if (netdl->pseudomode == 2)
1729  statusmixer->setText(QString("weights:"));
1730  if (netdl->pseudomode == 1)
1731  statusmixer->setText(QString("t-const:"));
1732  if (netdl->pseudomode == 3)
1733  statusmixer->setText(QString("biases:"));
1734  if (netdl->pseudomode == 4)
1735  statusmixer->setText(QString("gains:"));
1736  if (evonet->neuronlesions)
1737  statusmixer->setText(QString("neurons:"));
1738  layout->addWidget(statusmixer,0,0);
1739  Logger::info(QString("Mixer for n.%1 selected parameters\n").arg(evonet->neuronlesions+evonet->nselected));
1740  }
1741 
1742  float **gp;
1743  float *v;
1744  int l;
1745  int lt,li;
1746  int line=0;
1747 
1748  // selected parameters
1749  if (evonet->nselected > 0)
1750  {
1751  gp = evonet->selectedp;
1752  v = *gp;
1753  if (netdl->pseudomode == 2)
1754  {
1755  // weights
1756  lt = netdl->cneuron[0];
1757  li = netdl->cneuron[2];
1758  line = 0;
1759  for(int i=0;i<evonet->nselected;i++,v++,li++)
1760  {
1761  if (li > netdl->cneuron[3])
1762  {
1763  lt++;
1764  li = netdl->cneuron[2];
1765  line++;
1766  }
1767  layout->addWidget(new QLabel(evonet->neuronl[lt],this),1,i);
1768  EvoSlider* slide = new EvoSlider(v,(0 - evonet->getWrange()),evonet->getWrange(),this);
1769  connect( slide, SIGNAL(networkChanged()), netdl->rendNetwork, SLOT(update()) );
1770  layout->addWidget(slide,2,i);
1771  layout->addWidget(new QLabel(evonet->neuronl[li],this),3,i);
1772  }
1773  }
1774  else
1775  {
1776  // timeconstant(1), bias (2), gain(3)
1777  l = netdl->cneuron[0];
1778  for(int i=0;i<evonet->nselected;i++,v++,l++)
1779  {
1780  layout->addWidget(new QLabel(evonet->neuronl[l],this),1,i);
1781  EvoSlider* slide = new EvoSlider(v,(0 - evonet->getWrange()),evonet->getWrange(),this);
1782  connect( slide, SIGNAL(networkChanged()), netdl->rendNetwork, SLOT(update()) );
1783  layout->addWidget(slide,2,i);
1784  }
1785  }
1786  }
1787  else
1788  {
1789  // state of lesioned neurons
1790  for(int i=0;i<evonet->getNoNeurons();i++)
1791  if(evonet->neuronlesion[i])
1792  {
1793  layout->addWidget(new QLabel(evonet->neuronl[i],this),1,i);
1794  EvoSlider* slide = new EvoSlider(&evonet->neuronlesionVal[i],evonet->neuronrange[i][0],evonet->neuronrange[i][1],this);
1795  connect( slide, SIGNAL(networkChanged()), netdl->rendNetwork, SLOT(update()) );
1796  layout->addWidget(slide,2,i);
1797  }
1798  }
1799 
1800 }
1801 
1802 } //end namespace farsa
1803 
1804 // All the suff below is to restore the warning state on Windows
1805 #if defined(_MSC_VER)
1806  #pragma warning(pop)
1807 #endif