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