Great Gods of C++, Help A Poor Programmer

Discussion in 'C++' started by Matthew, Aug 18, 2004.

  1. Matthew

    Matthew Guest

    Recently, I began to write a program that demostrates memory
    representation as a network of concepts. AI is a hobby of mine and I
    just began to throw the program together. I didn't use the best style,
    but it still should have worked. (You can guess what's coming next!)
    It didn't! At the debug() call the program starts printing random
    data. I am running Mac OS X 10.3 using XCode. Here is the file, I hope
    it isn't too long. Thank you for your help.

    #include <iostream>
    #include <string>
    #include <vector>
    #include <stdlib.h>
    using namespace std;

    class Node
    {
    public:
    Node(string repr) { rep = repr;}
    void addConnection(Node * newc, bool typer) {
    connections.push_back(newc); types.push_back(typer); }
    string getRep() { return rep; }
    void setRep(string newr) { rep = newr; }
    void activate(int strength);

    void debug();
    private:
    string rep;
    vector<bool> types;
    vector<Node*> connections;
    };

    vector<Node> memory;
    bool temp;

    void Node::activate(int strength)
    {
    cout << strength << "\t" << rep << endl;
    srand(time(NULL));
    int ns = strength-(1 + rand() % (memory.size()-1));
    if(ns <= 0)
    return;
    for(int i = 0; i < connections.size(); ++i)
    {
    if(types)
    cout << "Isa: ";
    else
    cout << "P: ";
    (*connections).activate(ns);
    }
    }

    void Node::debug()
    {
    cout << "!DEBUGing " << rep << endl;
    for(int i = 0; i < connections.size(); ++i)
    {
    cout << i << " " << (*connections).getRep() << endl;
    }
    cout << "DEBUG!" << endl;
    }

    void addNewMem();
    void actMem();
    void addMem();
    void gatherConnections(Node * newMemory);
    void dumpMem();

    int main()
    {
    int choice = 0;;
    for(;;)
    {
    cout << "\nWhat to do?" << endl;
    cout << " (1) Add new memory" << endl;
    cout << " (2) Activate memory" << endl;
    cout << " (3) Exit" << endl;
    cin >> choice;
    getchar();
    switch(choice)
    {
    case 1:
    addNewMem();
    break;
    case 2:
    actMem();
    break;
    case 3:
    cout << "Positronic Brains Coming Soon To A Store Near You!" <<
    endl;
    return 0;
    default:
    cout << "Butthead" << endl;
    return 0;
    }
    }
    return 0;
    }

    void addNewMem()
    {
    char input;
    while(true)
    {
    addMem();
    cout << "Do you want to create another memory? [yn]: ";
    cin >> input;
    getchar();
    switch(input)
    {
    case 'y':
    break;
    case 'n':
    return;
    default:
    return;
    }
    }
    }

    void addMem()
    {
    dumpMem();
    string repr;
    cout << "Enter stimulus: ";
    getline(cin, repr);
    Node newMemory(repr);
    memory.push_back(newMemory);
    gatherConnections(&(memory[memory.size()-1]));
    dumpMem();
    }

    void gatherConnections(Node * newMemory)
    {
    char input;
    char input2;
    string minput;
    string typs;
    bool typer;
    cout << "Do you wish to make connections? [yn]: ";
    cin >> input2;
    getchar();
    switch(input2)
    {
    case 'y':
    break;
    case 'n':
    return;
    default:
    return;
    }
    while(true)
    {
    cout << "Enter name of memory to connect: ";
    getline(cin, minput);
    cout << "Enter type of connection [isa/p]: ";
    getline(cin, typs);
    if(typs == "isa")
    typer = true;
    else
    typer = false;
    for(int i = 0; i < memory.size(); ++i)
    {
    if(memory.getRep() == minput)
    {
    (*newMemory).addConnection(&memory, typer);
    memory.addConnection(newMemory, typer);
    (*newMemory).debug();
    memory.debug();
    break;
    }
    }
    cout << "Add another connection? [yn]: ";
    cin >> input;
    getchar();
    switch(input)
    {
    case 'y':
    break;
    case 'n':
    return;
    default:
    return;
    }
    }
    }

    void actMem()
    {
    string toAct;
    cout << "Enter stimulus: ";
    getline(cin, toAct);
    for(int i = 0; i < memory.size(); ++i)
    {
    if(memory.getRep() == toAct)
    {
    cout << "Begin: ";
    memory.activate(memory.size());
    break;
    }
    }
    }

    void dumpMem()
    {
    for(int i = 0; i < memory.size(); ++i)
    {
    cout << i << " " << &memory << " " << memory.getRep() << endl;
    }
    }
     
    Matthew, Aug 18, 2004
    #1
    1. Advertising

  2. Matthew

    Kai-Uwe Bux Guest

    Matthew wrote:

    > Recently, I began to write a program that demostrates memory
    > representation as a network of concepts. AI is a hobby of mine and I
    > just began to throw the program together. I didn't use the best style,
    > but it still should have worked. (You can guess what's coming next!)
    > It didn't! At the debug() call the program starts printing random
    > data. I am running Mac OS X 10.3 using XCode. Here is the file, I hope
    > it isn't too long. Thank you for your help.


    .....

    Hi,


    I compiled the program. Running the executable, I am confronted with a
    menu. Could you save me some time and tell me, how I reproduce that output
    you a worried about?


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Aug 18, 2004
    #2
    1. Advertising

  3. Matthew

    David Hilsee Guest

    "Matthew" <> wrote in message
    news:...
    > Recently, I began to write a program that demostrates memory
    > representation as a network of concepts. AI is a hobby of mine and I
    > just began to throw the program together. I didn't use the best style,
    > but it still should have worked. (You can guess what's coming next!)
    > It didn't! At the debug() call the program starts printing random
    > data. I am running Mac OS X 10.3 using XCode. Here is the file, I hope
    > it isn't too long. Thank you for your help.


    The biggest flaw that I see is that you used a std::vector when it was
    inappropriate. Adding elements to a vector will invalidate all of the
    pointers to the elements when it reallocates its internal buffer. The
    standard may be even more picky about it, but that's your problem, in a
    nutshell. The pointers in "vector<Node*> connections" could eventually
    point to a region of memory that has been deallocated by the
    std::vector<Node> memory, yielding undefined behavior that could explain
    garbage output. Consider using another container for the "memory", like a
    std::list<Node> or std::deque<Node>. It would probably be the easier to
    transition to std::deque<Node>, since it is more like a std::vector<Node>
    than std::list<Node>.

    --
    David Hilsee
     
    David Hilsee, Aug 19, 2004
    #3
  4. Matthew

    Matthew Guest

    Oops! Sorry about that.

    The program basically builds a little (or big) memory repository that
    can be used to demonstrate remembering or used in later problem
    solving programs. In the beginning menu you can add new memories,
    simulate remembering, or exit. When you choose the first option you
    can enter in the stimulus, in this case the program uses text as
    sensory input. For example you could enter "animal". It then asks to
    make connections to other memories. Since this is the first memory
    there is nothing to connect it to, so "n". It then prints a little
    dubugging message about the memory location of the new memory and then
    asks to make another memory. In this case we do so "y". Another
    dubugging message and we repeat. To get the problem I mentioned enter
    in this: (Note that there are two types of connections that are
    basically the same, besides the name. There are "isa" connections or
    "type of" and "p" connections or "property of". )

    What to do?
    (1) Add new memory
    (2) Activate memory
    (3) Exit
    1
    Enter stimulus: animal
    Do you wish to make connections? [yn]: n
    0 0x1800e00 animal
    Do you want to create another memory? [yn]: y
    0 0x1800e00 animal
    Enter stimulus: fish
    Do you wish to make connections? [yn]: y
    Enter name of memory to connect: animal
    Enter type of connection [isa/p]: isa
    !DEBUGing fish (More debugging: basically looks at an
    object and reports the connections)
    0 animal
    DEBUG!
    !DEBUGing animal
    0 fish
    DEBUG!
    Add another connection? [yn]: n
    0 0x1801120 animal
    1 0x1801144 fish
    Do you want to create another memory? [yn]: y
    0 0x1801120 animal
    1 0x1801144 fish
    Enter stimulus: swim
    Do you wish to make connections? [yn]: y
    Enter name of memory to connect: fish
    Enter type of connection [isa/p]: p
    !DEBUGing swim
    0 fish
    DEBUG!
    !DEBUGing fish
    ((((The messed up data has been deleted as google groups doesn't like
    it))))
    ^^^^^^^^^^^^^^^^^
    uhoh
    Here is the problem. Somehow the vector that contains the connections
    in "fish" is corrupted. The same thing happens if we delete the calls
    to debug() and activate a memory with the second menu option. (For
    reference activating means you conceptualize the memory then activate
    or "prime" memories connected. The farther from the source memory the
    weaker the activation, until there is no more left.)

    I hope this helps.

    Kai-Uwe Bux <> wrote in message news:<cg0c2i$r5b$>...
    > Matthew wrote:
    >
    > > Recently, I began to write a program that demostrates memory
    > > representation as a network of concepts. AI is a hobby of mine and I
    > > just began to throw the program together. I didn't use the best style,
    > > but it still should have worked. (You can guess what's coming next!)
    > > It didn't! At the debug() call the program starts printing random
    > > data. I am running Mac OS X 10.3 using XCode. Here is the file, I hope
    > > it isn't too long. Thank you for your help.

    >
    > ....
    >
    > Hi,
    >
    >
    > I compiled the program. Running the executable, I am confronted with a
    > menu. Could you save me some time and tell me, how I reproduce that output
    > you a worried about?
    >
    >
    > Best
    >
    > Kai-Uwe Bux
     
    Matthew, Aug 19, 2004
    #4
  5. Matthew

    Kai-Uwe Bux Guest

    Matthew wrote:

    > Oops! Sorry about that.
    >
    > The program basically builds a little (or big) memory repository that
    > can be used to demonstrate remembering or used in later problem
    > solving programs. In the beginning menu you can add new memories,
    > simulate remembering, or exit. When you choose the first option you
    > can enter in the stimulus, in this case the program uses text as
    > sensory input. For example you could enter "animal". It then asks to
    > make connections to other memories. Since this is the first memory
    > there is nothing to connect it to, so "n". It then prints a little
    > dubugging message about the memory location of the new memory and then
    > asks to make another memory. In this case we do so "y". Another
    > dubugging message and we repeat. To get the problem I mentioned enter
    > in this: (Note that there are two types of connections that are
    > basically the same, besides the name. There are "isa" connections or
    > "type of" and "p" connections or "property of". )
    >
    > What to do?
    > (1) Add new memory
    > (2) Activate memory
    > (3) Exit
    > 1
    > Enter stimulus: animal
    > Do you wish to make connections? [yn]: n
    > 0 0x1800e00 animal
    > Do you want to create another memory? [yn]: y
    > 0 0x1800e00 animal
    > Enter stimulus: fish
    > Do you wish to make connections? [yn]: y
    > Enter name of memory to connect: animal
    > Enter type of connection [isa/p]: isa
    > !DEBUGing fish (More debugging: basically looks at an
    > object and reports the connections)
    > 0 animal
    > DEBUG!
    > !DEBUGing animal
    > 0 fish
    > DEBUG!
    > Add another connection? [yn]: n
    > 0 0x1801120 animal
    > 1 0x1801144 fish
    > Do you want to create another memory? [yn]: y
    > 0 0x1801120 animal
    > 1 0x1801144 fish
    > Enter stimulus: swim
    > Do you wish to make connections? [yn]: y
    > Enter name of memory to connect: fish
    > Enter type of connection [isa/p]: p
    > !DEBUGing swim
    > 0 fish
    > DEBUG!
    > !DEBUGing fish
    > ((((The messed up data has been deleted as google groups doesn't like
    > it))))
    > ^^^^^^^^^^^^^^^^^
    > uhoh
    > Here is the problem. Somehow the vector that contains the connections
    > in "fish" is corrupted. The same thing happens if we delete the calls
    > to debug() and activate a memory with the second menu option. (For
    > reference activating means you conceptualize the memory then activate
    > or "prime" memories connected. The farther from the source memory the
    > weaker the activation, until there is no more left.)
    >
    > I hope this helps.
    >


    It does: when I try the sequence above, I get a segfault -- usually that
    indicates access to memory that has been returned. As David Hilsee has
    pointed out, this is a result of the re(al)location of std::vector<Node> as
    it grows. I replaced the line

    vector<Node> memory;

    by

    deque<Node> memory;

    and now, it seems to work. The standard [23.2.1.3] requires that inserts at
    the ends of a deque are not supposed to invalidate references to elements
    of the deque although iterators are invalidated. The std::list<> container
    would be safer in that iterators and references are most stable, but since
    you are using the size() method it might not be the best choice for your
    problem.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Aug 19, 2004
    #5
  6. Matthew

    Matthew Guest

    Thanks for your help, guys!


    "David Hilsee" <> wrote in message news:<>...
    > "Matthew" <> wrote in message
    > news:...
    > > Recently, I began to write a program that demostrates memory
    > > representation as a network of concepts. AI is a hobby of mine and I
    > > just began to throw the program together. I didn't use the best style,
    > > but it still should have worked. (You can guess what's coming next!)
    > > It didn't! At the debug() call the program starts printing random
    > > data. I am running Mac OS X 10.3 using XCode. Here is the file, I hope
    > > it isn't too long. Thank you for your help.

    >
    > The biggest flaw that I see is that you used a std::vector when it was
    > inappropriate. Adding elements to a vector will invalidate all of the
    > pointers to the elements when it reallocates its internal buffer. The
    > standard may be even more picky about it, but that's your problem, in a
    > nutshell. The pointers in "vector<Node*> connections" could eventually
    > point to a region of memory that has been deallocated by the
    > std::vector<Node> memory, yielding undefined behavior that could explain
    > garbage output. Consider using another container for the "memory", like a
    > std::list<Node> or std::deque<Node>. It would probably be the easier to
    > transition to std::deque<Node>, since it is more like a std::vector<Node>
    > than std::list<Node>.
     
    Matthew, Aug 20, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lyall
    Replies:
    1
    Views:
    417
    Lyall Pearce
    Feb 6, 2006
  2. Anthony Jones
    Replies:
    6
    Views:
    419
    Jeff Flinn
    Apr 8, 2004
  3. Vitamin
    Replies:
    0
    Views:
    105
    Vitamin
    Nov 24, 2003
  4. Eric I.
    Replies:
    0
    Views:
    264
    Eric I.
    Oct 5, 2008
  5. Rosario1903

    [OT] all the false gods can not save us

    Rosario1903, Nov 8, 2012, in forum: C Programming
    Replies:
    12
    Views:
    369
    Rod Pemberton
    Nov 13, 2012
Loading...

Share This Page