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