Changeset 732 for cpp/frams/model


Ignore:
Timestamp:
02/15/18 00:42:07 (6 years ago)
Author:
Maciej Komosinski
Message:

Added support for "checkpoints" (intermediate phases of development of the Model when converting between genetic encodings). See Model.checkpoint() and conv_f1.cpp for an example.

Location:
cpp/frams/model
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/model/defassign-f0-SDK.h

    r528 r732  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2016  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
  • cpp/frams/model/f0-SDK-classes.h

    r528 r732  
    155155 {"getInputNeuroIndex",0,1+2,"get input neuron index","p d(d)",PROCEDURE(p_getInputNeuroIndex),},
    156156 {"getInputWeight",0,1+2,"get input weight","p f(d)",PROCEDURE(p_getInputWeight),},
    157  {"classObject",0,1+2,"neuron class","o NeuroClass",GETONLY(classObject),},
     157 {"classObject",0,1+2,"neuron class","oNeuroClass",GETONLY(classObject),},
    158158 {0,0,0,}
    159159};
  • cpp/frams/model/model.cpp

    r726 r732  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2017  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    99#include <common/loggers/loggers.h>
    1010
     11#define F0_CHECKPOINT_LINE "checkpoint:"
     12
    1113Model::Model()
    1214{
     
    1820{
    1921        partmappingchanged = 0;
     22        using_checkpoints = false;
     23        is_checkpoint = false;
    2024        buildstatus = empty;
    2125        modelfromgenotype = 0;
     
    4751        f0genoknown = 0;
    4852        startenergy = mod.startenergy;
    49         if (mod.getStatus() == valid)
    50         {
    51                 modelfromgenotype = mod.modelfromgenotype;
    52                 {for (int i = 0; i < mod.getPartCount(); i++)
    53                         addPart(new Part(*mod.getPart(i))); }
    54         {for (int i = 0; i < mod.getJointCount(); i++)
     53        modelfromgenotype = mod.modelfromgenotype;
     54        for (int i = 0; i < mod.getPartCount(); i++)
     55                addPart(new Part(*mod.getPart(i)));
     56        for (int i = 0; i < mod.getJointCount(); i++)
    5557        {
    5658                Joint *oldj = mod.getJoint(i);
     
    5860                addJoint(j);
    5961                j->attachToParts(oldj->part1->refno, oldj->part2->refno);
    60         }}
    61         {for (int i = 0; i < mod.getNeuroCount(); i++)
     62        }
     63        for (int i = 0; i < mod.getNeuroCount(); i++)
    6264        {
    6365                Neuro *oldn = mod.getNeuro(i);
     
    6668                if (oldn->part_refno >= 0) n->attachToPart(oldn->part_refno);
    6769                else n->attachToJoint(oldn->joint_refno);
    68         }}
    69                 for (int i = 0; i < mod.getNeuroCount(); i++)
    70                 {
    71                         Neuro *oldn = mod.getNeuro(i);
    72                         Neuro *n = getNeuro(i);
    73                         for (int ni = 0; ni < oldn->getInputCount(); ni++)
    74                         {
    75                                 double w;
    76                                 Neuro *oldinput = oldn->getInput(ni, w);
    77                                 SString info = n->getInputInfo(ni);
    78                                 n->addInput(getNeuro(oldinput->refno), w, &info);
    79                         }
    80                 }
    81         }
    82 }
    83 
    84 
    85 Model::Model(const Geno &src, bool buildmaps)
     70        }
     71        for (int i = 0; i < mod.getNeuroCount(); i++)
     72        {
     73                Neuro *oldn = mod.getNeuro(i);
     74                Neuro *n = getNeuro(i);
     75                for (int ni = 0; ni < oldn->getInputCount(); ni++)
     76                {
     77                        double w;
     78                        Neuro *oldinput = oldn->getInput(ni, w);
     79                        SString info = n->getInputInfo(ni);
     80                        n->addInput(getNeuro(oldinput->refno), w, &info);
     81                }
     82        }
     83        updateRefno();
     84        if (using_checkpoints)
     85                for (vector<Model*>::const_iterator it = mod.checkpoints.begin(); it != mod.checkpoints.end(); it++)
     86                {
     87                Model *m = *it;
     88                Model *n = new Model(*m, m->autobuildmaps, false, true);
     89                checkpoints.push_back(n);
     90                }
     91}
     92
     93
     94Model::Model(const Geno &src, bool buildmaps, bool _using_checkpoints, bool _is_checkpoint)
    8695        :autobuildmaps(buildmaps)
    8796{
    88         init(src);
     97        init(src, _using_checkpoints, _is_checkpoint);
    8998}
    9099
     
    92101{
    93102        clear();
    94         open();
     103        open(mod.isUsingCheckpoints(), mod.isCheckpoint());
    95104        internalCopy(mod);
    96105        buildstatus = mod.buildstatus;
    97106}
    98107
    99 Model::Model(const Model &mod, bool buildmaps)
     108Model::Model(const Model &mod, bool buildmaps, bool _using_checkpoints, bool _is_checkpoint)
    100109        :autobuildmaps(buildmaps)
    101110{
    102111        init();
    103         open();
     112        open(_using_checkpoints, _is_checkpoint);
    104113        internalCopy(mod);
    105         buildstatus = mod.buildstatus;
    106 }
    107 
    108 void Model::init(const Geno &src)
     114        if (is_checkpoint)
     115                close();
     116        else
     117                buildstatus = mod.buildstatus;
     118        if (mod.map)
     119                map = new MultiMap(*mod.map);
     120        if (mod.f0map)
     121                f0map = new MultiMap(*mod.f0map);
     122}
     123
     124void Model::init(const Geno &src, bool _using_checkpoints, bool _is_checkpoint)
    109125{
    110126        init();
     127        using_checkpoints = _using_checkpoints;
     128        is_checkpoint = _is_checkpoint;
    111129        modelfromgenotype = 1;
    112130        geno = src;
     
    146164        geno = Geno();
    147165        f0geno = Geno();
     166        for (vector<Model*>::iterator it = checkpoints.begin(); it != checkpoints.end(); it++)
     167                delete *it;
     168        checkpoints.clear();
    148169}
    149170
     
    293314Model::ItemType Model::itemTypeFromLinePrefix(const char* line)
    294315{
    295 struct PrefixAndItem { const char* prefix; ItemType type; };
    296 static const PrefixAndItem types[]={ {"m:",ModelType},{"p:",PartType},{"j:",JointType},{"n:",NeuronType},{"c:",NeuronConnectionType},{NULL} };
    297 for(const PrefixAndItem *t=types;t->prefix!=NULL;t++)
    298         {
    299         const char* in=line;
    300         const char* pattern=t->prefix;
    301         for(;*in==*pattern;in++,pattern++)
    302                 if (*pattern==':')
    303                         return t->type;
    304         }
    305 return UnknownType;
     316        struct PrefixAndItem { const char* prefix; ItemType type; };
     317        static const PrefixAndItem types[] = { { "m:", ModelType }, { "p:", PartType }, { "j:", JointType }, { "n:", NeuronType }, { "c:", NeuronConnectionType }, { F0_CHECKPOINT_LINE, CheckpointType }, { NULL } };
     318        for (const PrefixAndItem *t = types; t->prefix != NULL; t++)
     319        {
     320                const char* in = line;
     321                const char* pattern = t->prefix;
     322                for (; *in == *pattern; in++, pattern++)
     323                        if (*pattern == ':')
     324                                return t->type;
     325        }
     326        return UnknownType;
    306327}
    307328
     
    311332        f0warnposition = -1;
    312333        MultiMap *convmap = autobuildmaps ? new MultiMap() : NULL;
    313         f0geno = (geno.getFormat() == '0') ? geno : geno.getConverted('0', convmap);
     334        f0geno = (geno.getFormat() == '0') ? geno : geno.getConverted('0', convmap, using_checkpoints);
    314335        f0genoknown = 1;
    315336        if (f0geno.isInvalid())
     
    331352        MultiRange frommap;
    332353        LoggerToMemory mh(LoggerBase::Enable | LoggerBase::DontBlock);
     354        Model *current_model = this;
    333355        for (; f0txt.getNextToken(pos, line, '\n'); lnum++)
    334356        {
    335                 const char* line_ptr=line.c_str();
     357                const char* line_ptr = line.c_str();
    336358                for (; *line_ptr; line_ptr++)
    337359                        if (!strchr(" \r\t", *line_ptr)) break;
     
    339361                if (!*line_ptr) continue;
    340362
    341                 const char* colon=strchr(line_ptr,':');
    342                 ItemType type=UnknownType;
     363                const char* colon = strchr(line_ptr, ':');
     364                ItemType type = UnknownType;
    343365                SString excluding_prefix;
    344                 if (colon!=NULL)
    345                         {
     366                if (colon != NULL)
     367                {
    346368                        colon++;
    347                         type=itemTypeFromLinePrefix(line_ptr);
     369                        type = itemTypeFromLinePrefix(line_ptr);
    348370                        for (; *colon; colon++)
    349371                                if (!strchr(" \r\t", *colon)) break;
    350                         excluding_prefix=colon;
    351                         }
    352                
     372                        excluding_prefix = colon;
     373                }
     374
    353375                if (autobuildmaps)
    354376                {
     
    357379                }
    358380                mh.reset();
    359                 if (addFromString(type, excluding_prefix, lnum, autobuildmaps ? (&frommap) : 0) == -1)
     381                if (type == CheckpointType)
     382                {
     383                        current_model->close();
     384                        current_model = new Model;
     385                        current_model->open(false, true);
     386                        checkpoints.push_back(current_model);
     387                }
     388                else if (current_model->addFromString(type, excluding_prefix, lnum, autobuildmaps ? (&frommap) : 0) == -1)
    360389                {
    361390                        buildstatus = invalid;
     
    371400        }
    372401        mh.disable();
    373         close();
     402        current_model->close();
    374403        if (convmap)
    375404        {
     
    503532                }
    504533        }
     534
     535        for (vector<Model*>::const_iterator it = checkpoints.begin(); it != checkpoints.end(); it++)
     536        {
     537                Geno g = (*it)->getF0Geno();
     538                gen += F0_CHECKPOINT_LINE "\n";
     539                gen += g.getGenes();
     540        }
     541
    505542        g = Geno(gen.c_str(), '0');
    506543}
     
    508545//////////////
    509546
    510 void Model::open()
     547void Model::open(bool _using_checkpoints, bool _is_checkpoint)
    511548{
    512549        if (buildstatus == building) return;
     550        using_checkpoints = _using_checkpoints;
     551        is_checkpoint = _is_checkpoint;
    513552        buildstatus = building;
    514553        modelfromgenotype = 0;
     
    518557}
    519558
     559int Model::getCheckpointCount()
     560{
     561        return checkpoints.size();
     562}
     563
     564Model* Model::getCheckpoint(int i)
     565{
     566        return checkpoints[i];
     567}
     568
    520569void Model::checkpoint()
    521 {}
     570{
     571        if (!using_checkpoints) return;
     572        updateRefno();
     573        Model *m = new Model(*this, false, false, true);
     574        checkpoints.push_back(m);
     575}
    522576
    523577void Model::setGeno(const Geno& newgeno)
     
    544598        if (buildstatus != building)
    545599                logPrintf("Model", "close", LOG_WARN, "Unexpected close() - no open()");
    546         if (internalcheck(building_live_model ? LIVE_CHECK : FINAL_CHECK) > 0)
     600        if (internalcheck(is_checkpoint ? CHECKPOINT_CHECK : (building_live_model ? LIVE_CHECK : FINAL_CHECK)) > 0)
    547601        {
    548602                buildstatus = valid;
     
    589643int Model::addFromString(ItemType item_type, const SString &singleline, const MultiRange* srcrange)
    590644{
    591         return addFromString(item_type,singleline, 0, srcrange);
     645        return addFromString(item_type, singleline, 0, srcrange);
    592646}
    593647
     
    612666        error_message = SString::empty();
    613667        ParamInterface::LoadOptions opts;
    614         switch(item_type)
    615                 {
    616                 case PartType:
    617                 {
     668        switch (item_type)
     669        {
     670        case PartType:
     671        {
    618672                Param partparam(f0_part_paramtab);
    619673                Part *p = new Part();
     
    626680                if (srcrange) p->setMapping(*srcrange);
    627681                return getPartCount() - 1;
    628                 }
    629 
    630                 case ModelType:
    631                 {
     682        }
     683
     684        case ModelType:
     685        {
    632686                Param modelparam(f0_model_paramtab);
    633687                modelparam.select(this);
     
    635689                if (opts.parse_failed) { error_message = "Invalid 'm:'"; return -1; }
    636690                return 0;
    637                 }
    638 
    639                 case JointType:
    640                 {
     691        }
     692
     693        case JointType:
     694        {
    641695                Param jointparam(f0_joint_paramtab);
    642696                Joint *j = new Joint();
     
    665719                        return -1;
    666720                }
    667                 }
    668 
    669                 case NeuronType:
    670                 {
     721        }
     722
     723        case NeuronType:
     724        {
    671725                Param neuroparam(f0_neuro_paramtab);
    672726                Neuro *nu = new Neuro();
     
    714768                        return neurons.size() - 1;
    715769                }
    716                 }
    717 
    718                 case NeuronConnectionType:                     
    719                 {
     770        }
     771
     772        case NeuronConnectionType:
     773        {
    720774                Param ncparam(f0_neuroconn_paramtab);
    721775                NeuroConn c;
     
    736790                error_message = SString::sprintf("Invalid reference to Neuro #%d", n1_ok ? c.n2_refno : c.n1_refno);
    737791                return -1;
    738                 }
    739 
    740                 case UnknownType: //handled by addFromString for uniform error handling
    741                         return -1;
    742                 }
     792        }
     793
     794        case CheckpointType: case UnknownType: //handled by addFromString for uniform error handling
     795                return -1;
     796        }
    743797        return -1;
    744798}
     
    747801/////////////
    748802
    749 /** change the sequence of neuro units
    750         and fix references in "-" objects (n-n connections)  */
    751 void Model::moveNeuro(int oldpos, int newpos)
    752 {
    753         if (oldpos == newpos) return; // nop!
    754         Neuro *n = getNeuro(oldpos);
    755         neurons -= oldpos;
    756         neurons.insert(newpos, n);
    757         // conn_refno could be broken -> fix it
    758 }
    759 
    760 ////////////
    761 
    762 void Model::updateNeuroRefno()
    763 {
     803void Model::updateRefno()
     804{
     805        for (int i = 0; i < parts.size(); i++)
     806                getPart(i)->refno = i;
     807        for (int i = 0; i < joints.size(); i++)
     808        {
     809                Joint *j = getJoint(i);
     810                j->refno = i;
     811                if (j->part1 && j->part2 && (j->part1 != j->part2))
     812                {
     813                        j->p1_refno = j->part1->refno;
     814                        j->p2_refno = j->part2->refno;
     815                }
     816        }
    764817        for (int i = 0; i < neurons.size(); i++)
    765         {
    766                 Neuro* n = (Neuro*)neurons(i);
    767                 n->refno = i;
    768         }
     818                getNeuro(i)->refno = i;
    769819}
    770820
     
    779829#define LINKFLAG 0x8000000
    780830
    781 void Model::updateRefno()
    782 {
    783         int i;
    784         for (i = 0; i < getPartCount(); i++) getPart(i)->refno = i;
    785         for (i = 0; i < getJointCount(); i++) getJoint(i)->refno = i;
    786         for (i = 0; i < getNeuroCount(); i++) getNeuro(i)->refno = i;
    787 }
    788 
    789831SString Model::nameForErrors() const
    790832{
     
    802844        int ret = 1;
    803845        shape = SHAPE_UNKNOWN;
     846        updateRefno();
    804847        if ((parts.size() == 0) && (neurons.size() == 0)) return 0;
    805848        if (parts.size() == 0)
     
    812855                        p = (Part*)parts(i);
    813856                        p->owner = this;
    814                         p->refno = i;
    815857                        if (checklevel > 0)
    816858                                p->mass = 0.0;
     
    907949                                        }
    908950                                }
    909                                 if (check != LIVE_CHECK)
     951                                if ((check != LIVE_CHECK) && (check != CHECKPOINT_CHECK))
    910952                                {
    911953                                        if (j->shape != Joint::SHAPE_FIXED)
     
    935977        }
    936978
    937         updateNeuroRefno(); // valid refno is important for n-n connections check (later)
    938 
    939979        for (i = 0; i < neurons.size(); i++)
    940980        {
     
    944984        }
    945985
    946         if (parts.size() && (checklevel > 0))
    947         {
    948                 for (i = 0; i < parts.size(); i++)
    949                 {
    950                         p = (Part*)parts(i);
    951                         if (p->mass <= 0.001)
    952                                 p->mass = 1.0;
    953                         p->flags &= ~LINKFLAG;
    954                 }
    955                 getPart(0)->flags |= LINKFLAG;
    956                 int change = 1;
    957                 while (change)
    958                 {
    959                         change = 0;
    960                         for (i = 0; i < joints.size(); i++)
    961                         {
    962                                 j = (Joint*)joints(i);
    963                                 if (j->part1->flags&LINKFLAG)
     986        if (check != CHECKPOINT_CHECK)
     987        {
     988
     989                if (parts.size() && (checklevel > 0))
     990                {
     991                        for (i = 0; i < parts.size(); i++)
     992                        {
     993                                p = (Part*)parts(i);
     994                                if (p->mass <= 0.001)
     995                                        p->mass = 1.0;
     996                                p->flags &= ~LINKFLAG;
     997                        }
     998                        getPart(0)->flags |= LINKFLAG;
     999                        int change = 1;
     1000                        while (change)
     1001                        {
     1002                                change = 0;
     1003                                for (i = 0; i < joints.size(); i++)
    9641004                                {
    965                                         if (!(j->part2->flags&LINKFLAG))
     1005                                        j = (Joint*)joints(i);
     1006                                        if (j->part1->flags&LINKFLAG)
    9661007                                        {
    967                                                 change = 1;
    968                                                 j->part2->flags |= LINKFLAG;
     1008                                                if (!(j->part2->flags&LINKFLAG))
     1009                                                {
     1010                                                        change = 1;
     1011                                                        j->part2->flags |= LINKFLAG;
     1012                                                }
    9691013                                        }
     1014                                        else
     1015                                                if (j->part2->flags&LINKFLAG)
     1016                                                {
     1017                                                if (!(j->part1->flags&LINKFLAG))
     1018                                                {
     1019                                                        change = 1;
     1020                                                        j->part1->flags |= LINKFLAG;
     1021                                                }
     1022                                                }
    9701023                                }
    971                                 else
    972                                         if (j->part2->flags&LINKFLAG)
    973                                         {
    974                                         if (!(j->part1->flags&LINKFLAG))
    975                                         {
    976                                                 change = 1;
    977                                                 j->part1->flags |= LINKFLAG;
    978                                         }
    979                                         }
    980                         }
    981                 }
    982                 for (i = 0; i < parts.size(); i++)
    983                 {
    984                         p = (Part*)parts(i);
    985                         if (!(p->flags&LINKFLAG))
    986                         {
    987                                 logPrintf("Model", "internalCheck", LOG_ERROR, "Not all parts connected (eg. Part #0 and Part #%d)%s", i, nameForErrors().c_str());
     1024                        }
     1025                        for (i = 0; i < parts.size(); i++)
     1026                        {
     1027                                p = (Part*)parts(i);
     1028                                if (!(p->flags&LINKFLAG))
     1029                                {
     1030                                        logPrintf("Model", "internalCheck", LOG_ERROR, "Not all parts connected (eg. Part #0 and Part #%d)%s", i, nameForErrors().c_str());
     1031                                        ret = 0;
     1032                                        break;
     1033                                }
     1034                        }
     1035                }
     1036
     1037                for (i = 0; i < joints.size(); i++)
     1038                {
     1039                        j = (Joint*)joints(i);
     1040                        if (j->p1_refno == j->p2_refno)
     1041                        {
     1042                                logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal self connection, Joint #%d%s", i, nameForErrors().c_str());
    9881043                                ret = 0;
    9891044                                break;
    9901045                        }
    991                 }
    992         }
    993 
    994         for (i = 0; i < joints.size(); i++)
    995         {
    996                 j = (Joint*)joints(i);
    997                 if (j->p1_refno == j->p2_refno)
    998                 {
    999                         logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal self connection, Joint #%d%s", i, nameForErrors().c_str());
    1000                         ret = 0;
    1001                         break;
    1002                 }
    1003                 for (k = i + 1; k < joints.size(); k++)
    1004                 {
    1005                         Joint* j2 = (Joint*)joints(k);
    1006                         if (((j->p1_refno == j2->p1_refno) && (j->p2_refno == j2->p2_refno))
    1007                                 || ((j->p1_refno == j2->p2_refno) && (j->p2_refno == j2->p1_refno)))
    1008                         {
    1009                                 logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal duplicate Joint #%d and Joint #%d%s", i, k, nameForErrors().c_str());
    1010                                 ret = 0;
    1011                                 break;
    1012                         }
    1013                 }
    1014         }
     1046                        for (k = i + 1; k < joints.size(); k++)
     1047                        {
     1048                                Joint* j2 = (Joint*)joints(k);
     1049                                if (((j->p1_refno == j2->p1_refno) && (j->p2_refno == j2->p2_refno))
     1050                                        || ((j->p1_refno == j2->p2_refno) && (j->p2_refno == j2->p1_refno)))
     1051                                {
     1052                                        logPrintf("Model", "internalCheck", LOG_ERROR, "Illegal duplicate Joint #%d and Joint #%d%s", i, k, nameForErrors().c_str());
     1053                                        ret = 0;
     1054                                        break;
     1055                                }
     1056                        }
     1057                }
     1058        }
     1059
    10151060        if (shape == SHAPE_ILLEGAL)
    10161061                ret = 0;
     
    12501295//////////////////////
    12511296
     1297int Model::elementToMap(ItemType type, int index)
     1298{
     1299        switch (type)
     1300        {
     1301        case PartType: return partToMap(index);
     1302        case JointType: return jointToMap(index);
     1303        case NeuronType: return neuroToMap(index);
     1304        default: return -1;
     1305        }
     1306}
     1307
     1308Model::TypeAndIndex Model::mapToElement(int map_index)
     1309{
     1310        if ((map_index >= 0) && (map_index < MODEL_MAPPING_OFFSET))
     1311                return TypeAndIndex(PartType, mapToPart(map_index));
     1312        if ((map_index >= MODEL_MAPPING_OFFSET) && (map_index < 2 * MODEL_MAPPING_OFFSET))
     1313                return TypeAndIndex(JointType, mapToJoint(map_index));
     1314        if ((map_index >= 2 * MODEL_MAPPING_OFFSET) && (map_index < 3 * MODEL_MAPPING_OFFSET))
     1315                return TypeAndIndex(NeuronType, mapToNeuro(map_index));
     1316        return TypeAndIndex();
     1317}
     1318
     1319int Model::partToMap(int i) { return MODEL_MAPPING_OFFSET + i; }
     1320int Model::jointToMap(int i) { return 2 * MODEL_MAPPING_OFFSET + i; }
     1321int Model::neuroToMap(int i) { return 3 * MODEL_MAPPING_OFFSET + i; }
     1322int Model::mapToPart(int i) { return i - MODEL_MAPPING_OFFSET; }
     1323int Model::mapToJoint(int i) { return i - 2 * MODEL_MAPPING_OFFSET; }
     1324int Model::mapToNeuro(int i) { return i - 3 * MODEL_MAPPING_OFFSET; }
     1325
     1326
     1327//////////////////////
     1328
    12521329class MinPart : public Part { public: MinPart() { Param par(f0_part_paramtab, this); par.setMin(); } };
    12531330class MaxPart : public Part { public: MaxPart() { Param par(f0_part_paramtab, this); par.setMax(); } };
  • cpp/frams/model/model.h

    r726 r732  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    1515
    1616extern ParamEntry f0_model_paramtab[];
    17 
    18 //#define EASYMAPDEBUG
    1917
    2018enum ModelBuildStatus { empty, building, invalid, valid };
     
    6462        /// make model map in build()
    6563        bool autobuildmaps;
     64        /// supports adding checkpoints
     65        bool using_checkpoints;
     66        /// means less strict validation
     67        bool is_checkpoint;
    6668        /// valid if build from f0 genotype
    6769        int f0errorposition;
     
    7577        SList parts, joints, neurons;
    7678        char partmappingchanged;
     79        vector<Model*> checkpoints;
    7780
    7881        void internalCopy(const Model &mod);
     
    9598                EDITING_CHECK, ///< Used in Model::validate(). Default validation - does not modify elements of the Model.
    9699                FINAL_CHECK,   ///< Used in Model::close() when a Model is built from a genotype. Like EDITING_CHECK, but also calculates Joint::d and Joint::rot.
    97                 LIVE_CHECK     ///< used in Model::close() when a Model is built from a Creature. Like FINAL_CHECK but does not limit joint length which could make some liveModels invalid.
     100                LIVE_CHECK,     ///< used in Model::close() when a Model is built from a Creature. Like FINAL_CHECK but does not limit joint length which could make some liveModels invalid.
     101                CHECKPOINT_CHECK     ///< used when storing checkpoint models. Like LIVE_CHECK, excluding consistency check (disjoint parts are acceptable)
    98102        };
    99103protected:
    100104        ShapeType shape;
    101105
    102         void updateNeuroRefno(); // set Neuro::refno for all neurons
    103106        SString nameForErrors() const;
    104107        int internalcheck(CheckType check);
    105108
    106         void moveNeuro(int oldpos, int newpos);
    107 
    108         void init(const Geno &srcgen);
     109        void init(const Geno &srcgen, bool _using_checkpoints, bool _is_checkpoint);
    109110        void init();
    110111
     
    134135        int getErrorPosition(bool includingwarnings = false);
    135136        ShapeType getShapeType() const { return shape; }
     137        bool isUsingCheckpoints() const { return using_checkpoints; }
     138        bool isCheckpoint() const { return is_checkpoint; }
    136139
    137140        void updateRefno(); // set ::refno for all elements
     141
     142        int getCheckpointCount();
     143        Model* getCheckpoint(int i);
    138144
    139145        /// The bounding box size. Valid if the model is valid. Read only.
     
    153159           @see getMap()
    154160           */
    155         Model(const Geno &src, bool buildmaps = false);
    156         Model(const Model &mod, bool buildmaps = false);
     161        Model(const Geno &src, bool buildmaps = false, bool _using_checkpoints = false, bool _is_checkpoint = false);
     162        Model(const Model &mod, bool buildmaps = false, bool _using_checkpoints = false, bool _is_checkpoint = false);
    157163        /** duplicate the model.
    158164                the resulting object's status is 'building' (opened).
     
    255261        void clear();
    256262
    257         enum ItemType { UnknownType,ModelType,PartType,JointType,NeuronType,NeuronConnectionType };
     263        enum ItemType { UnknownType, ModelType, PartType, JointType, NeuronType, NeuronConnectionType, CheckpointType };
    258264        static ItemType itemTypeFromLinePrefix(const char* line);
    259265        /** Execute single line of <B>f0</B> genotype.
     
    264270                @param srcrange source genotype range which will be mapped to this element
    265271                */
    266         int addFromString(ItemType item_type,const SString &singleline, int line_num, const MultiRange* srcrange = NULL);
     272        int addFromString(ItemType item_type, const SString &singleline, int line_num, const MultiRange* srcrange = NULL);
    267273        /** Execute single line of <B>f0</B> genotype - compatiblity variant */
    268         int addFromString(ItemType item_type,const SString &singleline, const MultiRange* srcrange = NULL);
     274        int addFromString(ItemType item_type, const SString &singleline, const MultiRange* srcrange = NULL);
    269275        /** Execute single line of <B>f0</B> genotype - low level variant, used by Model::build(), error messages returned as string instead of calling logger */
    270         int addFromStringNoLog(ItemType item_type,const SString &singleline, SString& error_message, const MultiRange* srcrange = 0);
     276        int addFromStringNoLog(ItemType item_type, const SString &singleline, SString& error_message, const MultiRange* srcrange = 0);
    271277
    272278        /// separate build stages (for future use)
     
    289295        /// or modify the model created from the genotype.
    290296        /// Between open() and close() the model is not fully usable.
    291         void open();
     297        void open(bool _using_checkpoints = false, bool _is_checkpoint = false);
    292298
    293299        /// Current model written as f0 genotype while building
     
    379385        void buildUsingSolidShapeTypes(const Model& src_ballandstick_shapes, Part::Shape use_shape = Part::SHAPE_CYLINDER, float thickness = 0.2);
    380386
    381 #ifdef EASYMAPDEBUG
    382         static int partToMap(int i) {return 0+i;}
    383         static int jointToMap(int i) {return 10+i;}
    384         static int neuroToMap(int i) {return 20+i;}
    385         static int mapToPart(int i) {return i-0;}
    386         static int mapToJoint(int i) {return i-10;}
    387         static int mapToNeuro(int i) {return i-20;}
    388 #else
    389         static int partToMap(int i) { return 0x10000000 + i; }
    390         static int jointToMap(int i) { return 0x20000000 + i; }
    391         static int neuroToMap(int i) { return 0x30000000 + i; }
    392         static int mapToPart(int i) { return i - 0x10000000; }
    393         static int mapToJoint(int i) { return i - 0x20000000; }
    394         static int mapToNeuro(int i) { return i - 0x30000000; }
    395 #endif
     387protected:
     388        static const int MODEL_MAPPING_OFFSET = 0x10000000;
     389public:
     390        static int elementToMap(ItemType t, int i);
     391        struct TypeAndIndex
     392        {
     393                ItemType type; int index;
     394                TypeAndIndex() :type(UnknownType), index(0) {}
     395                TypeAndIndex(ItemType _type, int _index) :type(_type), index(_index) {}
     396        };
     397        static TypeAndIndex mapToElement(int i);
     398        static int partToMap(int i);
     399        static int jointToMap(int i);
     400        static int neuroToMap(int i);
     401        static int mapToPart(int i);
     402        static int mapToJoint(int i);
     403        static int mapToNeuro(int i);
    396404
    397405        static void makeGenToGenMap(MultiMap& result, const MultiMap& gen1tomodel, const MultiMap& gen2tomodel);
  • cpp/frams/model/modelobj.cpp

    r722 r732  
    77ParamEntry modelobj_paramtab[] =
    88{
    9         { "Model", 1, 16, "Model", },
     9        { "Model", 1, 21, "Model", },
    1010        { "se", 0, PARAM_NOSTATIC, "startenergy", "f", FIELD(startenergy), },
    1111        { "Vstyle", 0, PARAM_NOSTATIC, "vis_style", "s", FIELD(vis_style), },
    1212
    13         { "geno", 0, PARAM_NOSTATIC | PARAM_READONLY, "geno", "o Geno", GETONLY(geno), },
    14         { "newFromString", 0, 0, "create new object", "p oModel(s genotype)", PROCEDURE(p_newfromstring), },
    15         { "newFromGeno", 0, 0, "create new object", "p oModel(oGeno)", PROCEDURE(p_newfromgeno), },
     13        { "geno", 0, PARAM_NOSTATIC | PARAM_READONLY, "Geno", "oGeno", GETONLY(geno), },
     14        { "newFromString", 0, 0, "Create a new object", "p oModel(s genotype)", PROCEDURE(p_newfromstring), },
     15        { "newFromGeno", 0, 0, "Create a new object", "p oModel(oGeno)", PROCEDURE(p_newfromgeno), },
     16        { "newWithCheckpoints", 0, 0, "Create a new object", "p oModel(x Geno object or string genotype)", PROCEDURE(p_newwithcheckpoints), "Creates a Model with the \"Checkpoints\" option enabled. Genotype converters supporting Checkpoints provide a sequence of Models that reflects development stages of the creature (this sequence is used purely for debugging and visualization of phenotype growth/development). Checkpoint Models can be accessed using getCheckpoint(i) for i ranging from 0 to numcheckpoints-1. Models created without the Checkpoint option and Models coming from unsupported converters have numcheckpoints=0." },
    1617
    17         { "numparts", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "number of parts", "d", GETONLY(numparts), },
    18         { "numjoints", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "number of joints", "d", GETONLY(numjoints), },
    19         { "numneurons", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "number of neurons", "d", GETONLY(numneurons), },
    20         { "numconnections", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "number of neuron connections", "d", GETONLY(numconnections), },
     18        { "numparts", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "Number of parts", "d", GETONLY(numparts), },
     19        { "numjoints", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "Number of joints", "d", GETONLY(numjoints), },
     20        { "numneurons", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "Number of neurons", "d", GETONLY(numneurons), },
     21        { "numconnections", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "Number of neuron connections", "d", GETONLY(numconnections), },
    2122
    2223        { "getPart", 0, PARAM_USERHIDDEN | PARAM_NOSTATIC, "getPart (static model information)", "p oPart(d index)", PROCEDURE(p_getpart), },
     
    2425        { "getNeuroDef", 0, PARAM_USERHIDDEN | PARAM_NOSTATIC, "getNeuroDef", "p oNeuroDef(d index)", PROCEDURE(p_getneuro), },
    2526
    26         { "size_x", 0, PARAM_READONLY | PARAM_NOSTATIC | PARAM_DEPRECATED, "bounding box x size", "f", FIELD(size.x), "(size_x,size_y,size_z) are dimensions of the axis-aligned bounding box of the creature, including imaginary Part sizes (Part.s, usually 1.0). A creature consisting of a single default part has the size of (2.0,2.0,2.0) - twice the Part.s value (like a sphere diameter is twice its radius).\nSee also: Creature.moveAbs" },
    27         { "size_y", 0, PARAM_READONLY | PARAM_NOSTATIC | PARAM_DEPRECATED, "bounding box y size", "f", FIELD(size.y), "See Model.size_x" },
    28         { "size_z", 0, PARAM_READONLY | PARAM_NOSTATIC | PARAM_DEPRECATED, "bounding box z size", "f", FIELD(size.z), "See Model.size_x" },
     27        { "size_x", 0, PARAM_READONLY | PARAM_NOSTATIC | PARAM_DEPRECATED, "Bounding box x size", "f", FIELD(size.x), "(size_x,size_y,size_z) are dimensions of the axis-aligned bounding box of the creature, including imaginary Part sizes (Part.s, usually 1.0). A creature consisting of a single default part has the size of (2.0,2.0,2.0) - twice the Part.s value (like a sphere diameter is twice its radius).\nSee also: Creature.moveAbs" },
     28        { "size_y", 0, PARAM_READONLY | PARAM_NOSTATIC | PARAM_DEPRECATED, "Bounding box y size", "f", FIELD(size.y), "See Model.size_x" },
     29        { "size_z", 0, PARAM_READONLY | PARAM_NOSTATIC | PARAM_DEPRECATED, "Bounding box z size", "f", FIELD(size.z), "See Model.size_x" },
    2930        { "bboxSize", 0, PARAM_READONLY | PARAM_NOSTATIC, "Bounding box size", "oXYZ", GETONLY(bboxsize) },
     31        { "numcheckpoints", 0, PARAM_DONTSAVE | PARAM_READONLY | PARAM_NOSTATIC, "Number of checkpoints", "d", GETONLY(numcheckpoints) },
     32        { "getCheckpoint", 0, PARAM_USERHIDDEN | PARAM_NOSTATIC, "getCheckpoint", "p oModel(d index)", PROCEDURE(p_getcheckpoint),
     33        "Checkpoint Model objects are only valid as long as the parent Model object exists.\n"
     34        "See also: Model.newWithCheckpoints()\n\n"
     35        "// incorrect usage - calling getCheckpoint() on a temporary object:\n"
     36        "var c=Model.newWithCheckpoints(\"XXX\").getCheckpoint(1).genotype.geno;\n\n"
     37        "// correct usage - keeping the parent Model reference in 'm':\n"
     38        "var m=Model.newWithCheckpoints(\"XXX\");\n"
     39        "var c=m.getCheckpoint(1).genotype.geno;\n"
     40        },
     41        { "shape_type", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "Shape type", "d 0 3 ~Unknown~Illegal~Ball-and-stick~Solids", GETONLY(shape_type) },
     42        { "solid_model", 0, PARAM_DONTSAVE | PARAM_NOSTATIC | PARAM_READONLY, "Solid shapes model", "oModel", GETONLY(solid_model), "Conversion of this Model to solid shapes. Note! Only available when this Model has shape_type==2 (Ball-and-stick)." },
    3043
    3144        { 0, 0, 0, },
     
    5770}
    5871
     72void ModelObj::p_newwithcheckpoints(ExtValue *args, ExtValue *ret)
     73{
     74        Model *m = NULL;
     75        if (args[0].getType() == TString)
     76                m = new Model(Geno(args[0].getString()), false, true);
     77        else
     78        {
     79                Geno *g = GenoObj::fromObject(args[0].getObject(), false);
     80                if (g)
     81                        m = new Model(*g, false, true);
     82                else
     83                        logPrintf("Model", "newWithCheckpoints", LOG_ERROR, "Geno or string expected, %s found", args[0].typeDescription().c_str());
     84        }
     85
     86        if (m != NULL)
     87                *ret = makeDynamicObject(m);
     88        else
     89                ret->setEmpty();
     90}
     91
    5992Param& ModelObj::getStaticParam()
    6093{
    6194#ifdef __CODEGUARD__
    6295        static ModelObj static_modelobj;
    63         static Param static_modelparam(modelobj_paramtab,&static_modelobj);
     96        static Param static_modelparam(modelobj_paramtab, &static_modelobj);
    6497#else
    6598        static Param static_modelparam(modelobj_paramtab);
     
    131164        *ret = Pt3D_Ext::makeDynamicObject(new Pt3D_Ext(size));
    132165}
     166
     167void ModelObj::p_getcheckpoint(PARAMPROCARGS)
     168{
     169        int i = args->getInt();
     170        if ((i < 0) || (i >= getCheckpointCount()))
     171        {
     172                ret->setEmpty();
     173                return;
     174        }
     175        ret->setObject(makeStaticObject(getCheckpoint(i)));
     176}
     177
     178void ModelObj::get_solid_model(ExtValue *ret)
     179{
     180        if (getShapeType() != Model::SHAPE_BALL_AND_STICK)
     181                ret->setEmpty();
     182        Model *m = new Model;
     183        m->open();
     184        m->buildUsingSolidShapeTypes(*this);
     185        m->close();
     186        *ret = makeDynamicObject(m);
     187}
     188
     189void ModelObj::get_shape_type(ExtValue *ret)
     190{
     191        ret->setInt(getShapeType());
     192}
  • cpp/frams/model/modelobj.h

    r722 r732  
    1414        PARAMPROCDEF(p_newfromstring);
    1515        PARAMPROCDEF(p_newfromgeno);
     16        PARAMPROCDEF(p_newwithcheckpoints);
    1617
    1718#define GETDELEGATE(name,type,value) PARAMGETDEF(name) {arg1->set ## type (value);}
     
    2021        GETDELEGATE(numneurons, Int, getNeuroCount())
    2122        GETDELEGATE(numconnections, Int, getConnectionCount())
     23        GETDELEGATE(numcheckpoints, Int, getCheckpointCount())
    2224#undef GETDELEGATE
    2325
     
    2628        PARAMPROCDEF(p_getneuro);
    2729        PARAMGETDEF(bboxsize);
     30        PARAMPROCDEF(p_getcheckpoint);
     31        PARAMGETDEF(shape_type);
     32        PARAMGETDEF(solid_model);
    2833
    2934#undef STATRICKCLASS
Note: See TracChangeset for help on using the changeset viewer.