lemon/list_graph.h
author deba
Mon, 03 Apr 2006 09:45:23 +0000
changeset 2031 080d51024ac5
parent 1999 2ff283124dfc
child 2076 10681ee9d8ae
permissions -rw-r--r--
Correcting the structure of the graph's and adaptor's map.
The template assign operators and map iterators can be used for adaptors also.

Some bugfix in the adaptors

New class SwapBpUGraphAdaptor which swaps the two nodeset of the graph.
alpar@948
     1
/* -*- C++ -*-
alpar@948
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@948
     8
 *
alpar@948
     9
 * Permission to use, modify and distribute this software is granted
alpar@948
    10
 * provided that this copyright notice appears in all copies. For
alpar@948
    11
 * precise terms see the accompanying LICENSE file.
alpar@948
    12
 *
alpar@948
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@948
    14
 * express or implied, and with no claim as to its suitability for any
alpar@948
    15
 * purpose.
alpar@948
    16
 *
alpar@948
    17
 */
alpar@395
    18
alpar@921
    19
#ifndef LEMON_LIST_GRAPH_H
alpar@921
    20
#define LEMON_LIST_GRAPH_H
alpar@395
    21
alpar@948
    22
///\ingroup graphs
alpar@948
    23
///\file
klao@1909
    24
///\brief ListGraph, ListUGraph classes.
alpar@948
    25
deba@1999
    26
#include <lemon/bits/base_extender.h>
deba@1791
    27
#include <lemon/bits/graph_extender.h>
deba@782
    28
deba@1774
    29
#include <lemon/error.h>
deba@1774
    30
deba@1979
    31
#include <vector>
alpar@1011
    32
#include <list>
deba@782
    33
alpar@921
    34
namespace lemon {
alpar@395
    35
klao@946
    36
  class ListGraphBase {
alpar@406
    37
alpar@949
    38
  protected:
klao@946
    39
    struct NodeT {
deba@1470
    40
      int first_in, first_out;
alpar@397
    41
      int prev, next;
alpar@395
    42
    };
klao@946
    43
 
klao@946
    44
    struct EdgeT {
alpar@986
    45
      int target, source;
alpar@397
    46
      int prev_in, prev_out;
alpar@397
    47
      int next_in, next_out;
alpar@395
    48
    };
alpar@395
    49
alpar@395
    50
    std::vector<NodeT> nodes;
klao@946
    51
alpar@397
    52
    int first_node;
klao@946
    53
alpar@397
    54
    int first_free_node;
klao@946
    55
alpar@395
    56
    std::vector<EdgeT> edges;
klao@946
    57
alpar@397
    58
    int first_free_edge;
alpar@395
    59
    
deba@782
    60
  public:
alpar@395
    61
    
klao@946
    62
    typedef ListGraphBase Graph;
alpar@397
    63
    
klao@946
    64
    class Node {
marci@975
    65
      friend class ListGraphBase;
klao@946
    66
    protected:
alpar@395
    67
klao@946
    68
      int id;
deba@2031
    69
      explicit Node(int pid) { id = pid;}
alpar@395
    70
klao@946
    71
    public:
klao@946
    72
      Node() {}
klao@946
    73
      Node (Invalid) { id = -1; }
klao@946
    74
      bool operator==(const Node& node) const {return id == node.id;}
klao@946
    75
      bool operator!=(const Node& node) const {return id != node.id;}
klao@946
    76
      bool operator<(const Node& node) const {return id < node.id;}
klao@946
    77
    };
deba@782
    78
klao@946
    79
    class Edge {
marci@975
    80
      friend class ListGraphBase;
klao@946
    81
    protected:
deba@782
    82
klao@946
    83
      int id;
deba@2031
    84
      explicit Edge(int pid) { id = pid;}
alpar@395
    85
klao@946
    86
    public:
klao@946
    87
      Edge() {}
klao@946
    88
      Edge (Invalid) { id = -1; }
klao@946
    89
      bool operator==(const Edge& edge) const {return id == edge.id;}
klao@946
    90
      bool operator!=(const Edge& edge) const {return id != edge.id;}
klao@946
    91
      bool operator<(const Edge& edge) const {return id < edge.id;}
klao@946
    92
    };
klao@946
    93
klao@946
    94
klao@946
    95
klao@946
    96
    ListGraphBase()
deba@782
    97
      : nodes(), first_node(-1),
deba@782
    98
	first_free_node(-1), edges(), first_free_edge(-1) {}
deba@782
    99
alpar@395
   100
    
alpar@813
   101
    /// Maximum node ID.
alpar@813
   102
    
alpar@813
   103
    /// Maximum node ID.
alpar@813
   104
    ///\sa id(Node)
deba@1791
   105
    int maxNodeId() const { return nodes.size()-1; } 
klao@946
   106
alpar@813
   107
    /// Maximum edge ID.
alpar@813
   108
    
alpar@813
   109
    /// Maximum edge ID.
alpar@813
   110
    ///\sa id(Edge)
deba@1791
   111
    int maxEdgeId() const { return edges.size()-1; }
alpar@395
   112
deba@2031
   113
    Node source(Edge e) const { return Node(edges[e.id].source); }
deba@2031
   114
    Node target(Edge e) const { return Node(edges[e.id].target); }
alpar@395
   115
alpar@395
   116
klao@946
   117
    void first(Node& node) const { 
klao@946
   118
      node.id = first_node;
klao@946
   119
    }
klao@946
   120
klao@946
   121
    void next(Node& node) const {
klao@946
   122
      node.id = nodes[node.id].next;
klao@946
   123
    }
klao@946
   124
klao@946
   125
klao@946
   126
    void first(Edge& e) const { 
klao@946
   127
      int n;
klao@946
   128
      for(n = first_node; 
klao@946
   129
	  n!=-1 && nodes[n].first_in == -1; 
klao@946
   130
	  n = nodes[n].next);
klao@946
   131
      e.id = (n == -1) ? -1 : nodes[n].first_in;
klao@946
   132
    }
klao@946
   133
klao@946
   134
    void next(Edge& edge) const {
klao@946
   135
      if (edges[edge.id].next_in != -1) {
klao@946
   136
	edge.id = edges[edge.id].next_in;
klao@946
   137
      } else {
klao@946
   138
	int n;
alpar@986
   139
	for(n = nodes[edges[edge.id].target].next;
klao@946
   140
	  n!=-1 && nodes[n].first_in == -1; 
klao@946
   141
	  n = nodes[n].next);
klao@946
   142
	edge.id = (n == -1) ? -1 : nodes[n].first_in;
klao@946
   143
      }      
klao@946
   144
    }
klao@946
   145
klao@946
   146
    void firstOut(Edge &e, const Node& v) const {
klao@946
   147
      e.id = nodes[v.id].first_out;
klao@946
   148
    }
klao@946
   149
    void nextOut(Edge &e) const {
klao@946
   150
      e.id=edges[e.id].next_out;
klao@946
   151
    }
klao@946
   152
klao@946
   153
    void firstIn(Edge &e, const Node& v) const {
klao@946
   154
      e.id = nodes[v.id].first_in;
klao@946
   155
    }
klao@946
   156
    void nextIn(Edge &e) const {
klao@946
   157
      e.id=edges[e.id].next_in;
klao@946
   158
    }
klao@946
   159
alpar@813
   160
    
klao@946
   161
    static int id(Node v) { return v.id; }
klao@946
   162
    static int id(Edge e) { return e.id; }
alpar@395
   163
deba@1791
   164
    static Node nodeFromId(int id) { return Node(id);}
deba@1791
   165
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   166
alpar@397
   167
    /// Adds a new node to the graph.
alpar@397
   168
alpar@813
   169
    /// \warning It adds the new node to the front of the list.
alpar@397
   170
    /// (i.e. the lastly added node becomes the first.)
klao@946
   171
    Node addNode() {     
alpar@397
   172
      int n;
alpar@397
   173
      
klao@946
   174
      if(first_free_node==-1) {
klao@946
   175
	n = nodes.size();
klao@946
   176
	nodes.push_back(NodeT());
klao@946
   177
      } else {
alpar@397
   178
	n = first_free_node;
alpar@397
   179
	first_free_node = nodes[n].next;
alpar@397
   180
      }
alpar@397
   181
      
alpar@397
   182
      nodes[n].next = first_node;
alpar@397
   183
      if(first_node != -1) nodes[first_node].prev = n;
alpar@397
   184
      first_node = n;
alpar@397
   185
      nodes[n].prev = -1;
alpar@397
   186
      
alpar@397
   187
      nodes[n].first_in = nodes[n].first_out = -1;
alpar@397
   188
      
klao@946
   189
      return Node(n);
alpar@395
   190
    }
alpar@395
   191
    
alpar@395
   192
    Edge addEdge(Node u, Node v) {
klao@946
   193
      int n;      
klao@946
   194
klao@946
   195
      if (first_free_edge == -1) {
klao@946
   196
	n = edges.size();
klao@946
   197
	edges.push_back(EdgeT());
klao@946
   198
      } else {
alpar@397
   199
	n = first_free_edge;
alpar@397
   200
	first_free_edge = edges[n].next_in;
alpar@397
   201
      }
alpar@397
   202
      
alpar@986
   203
      edges[n].source = u.id; 
alpar@986
   204
      edges[n].target = v.id;
alpar@395
   205
klao@946
   206
      edges[n].next_out = nodes[u.id].first_out;
klao@946
   207
      if(nodes[u.id].first_out != -1) {
klao@946
   208
	edges[nodes[u.id].first_out].prev_out = n;
klao@946
   209
      }
klao@946
   210
      
klao@946
   211
      edges[n].next_in = nodes[v.id].first_in;
klao@946
   212
      if(nodes[v.id].first_in != -1) {
klao@946
   213
	edges[nodes[v.id].first_in].prev_in = n;
klao@946
   214
      }
klao@946
   215
      
alpar@397
   216
      edges[n].prev_in = edges[n].prev_out = -1;
alpar@397
   217
	
klao@946
   218
      nodes[u.id].first_out = nodes[v.id].first_in = n;
alpar@397
   219
klao@946
   220
      return Edge(n);
alpar@395
   221
    }
alpar@774
   222
    
klao@946
   223
    void erase(const Node& node) {
klao@946
   224
      int n = node.id;
klao@946
   225
      
klao@946
   226
      if(nodes[n].next != -1) {
klao@946
   227
	nodes[nodes[n].next].prev = nodes[n].prev;
klao@946
   228
      }
klao@946
   229
      
klao@946
   230
      if(nodes[n].prev != -1) {
klao@946
   231
	nodes[nodes[n].prev].next = nodes[n].next;
klao@946
   232
      } else {
klao@946
   233
	first_node = nodes[n].next;
klao@946
   234
      }
klao@946
   235
      
klao@946
   236
      nodes[n].next = first_free_node;
klao@946
   237
      first_free_node = n;
alpar@395
   238
alpar@774
   239
    }
alpar@774
   240
    
klao@946
   241
    void erase(const Edge& edge) {
klao@946
   242
      int n = edge.id;
alpar@397
   243
      
klao@946
   244
      if(edges[n].next_in!=-1) {
alpar@397
   245
	edges[edges[n].next_in].prev_in = edges[n].prev_in;
klao@946
   246
      }
klao@946
   247
klao@946
   248
      if(edges[n].prev_in!=-1) {
alpar@397
   249
	edges[edges[n].prev_in].next_in = edges[n].next_in;
klao@946
   250
      } else {
alpar@986
   251
	nodes[edges[n].target].first_in = edges[n].next_in;
klao@946
   252
      }
klao@946
   253
alpar@397
   254
      
klao@946
   255
      if(edges[n].next_out!=-1) {
alpar@397
   256
	edges[edges[n].next_out].prev_out = edges[n].prev_out;
klao@946
   257
      } 
klao@946
   258
klao@946
   259
      if(edges[n].prev_out!=-1) {
alpar@397
   260
	edges[edges[n].prev_out].next_out = edges[n].next_out;
klao@946
   261
      } else {
alpar@986
   262
	nodes[edges[n].source].first_out = edges[n].next_out;
klao@946
   263
      }
alpar@397
   264
      
alpar@397
   265
      edges[n].next_in = first_free_edge;
alpar@695
   266
      first_free_edge = n;      
alpar@397
   267
alpar@397
   268
    }
alpar@397
   269
alpar@397
   270
    void clear() {
deba@782
   271
      edges.clear();
deba@782
   272
      nodes.clear();
klao@946
   273
      first_node = first_free_node = first_free_edge = -1;
deba@937
   274
    }
deba@937
   275
alpar@949
   276
  protected:
alpar@1546
   277
    void _changeTarget(Edge e, Node n) 
alpar@949
   278
    {
alpar@949
   279
      if(edges[e.id].next_in != -1)
alpar@949
   280
	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
alpar@949
   281
      if(edges[e.id].prev_in != -1)
alpar@949
   282
	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
alpar@986
   283
      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
deba@1702
   284
      if (nodes[n.id].first_in != -1) {
deba@1702
   285
	edges[nodes[n.id].first_in].prev_in = e.id;
deba@1702
   286
      }
alpar@986
   287
      edges[e.id].target = n.id;
alpar@949
   288
      edges[e.id].prev_in = -1;
alpar@949
   289
      edges[e.id].next_in = nodes[n.id].first_in;
alpar@949
   290
      nodes[n.id].first_in = e.id;
alpar@949
   291
    }
alpar@1546
   292
    void _changeSource(Edge e, Node n) 
alpar@949
   293
    {
alpar@949
   294
      if(edges[e.id].next_out != -1)
alpar@949
   295
	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
alpar@949
   296
      if(edges[e.id].prev_out != -1)
alpar@949
   297
	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
alpar@986
   298
      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
deba@1702
   299
      if (nodes[n.id].first_out != -1) {
deba@1702
   300
	edges[nodes[n.id].first_out].prev_out = e.id;
deba@1702
   301
      }
alpar@986
   302
      edges[e.id].source = n.id;
alpar@949
   303
      edges[e.id].prev_out = -1;
alpar@949
   304
      edges[e.id].next_out = nodes[n.id].first_out;
alpar@949
   305
      nodes[n.id].first_out = e.id;
alpar@949
   306
    }
alpar@949
   307
alpar@919
   308
  };
deba@909
   309
deba@1979
   310
  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
alpar@400
   311
deba@1718
   312
  /// \addtogroup graphs
deba@1718
   313
  /// @{
alpar@400
   314
alpar@948
   315
  ///A list graph class.
alpar@400
   316
alpar@948
   317
  ///This is a simple and fast erasable graph implementation.
alpar@948
   318
  ///
alpar@1010
   319
  ///It addition that it conforms to the
alpar@1010
   320
  ///\ref concept::ErasableGraph "ErasableGraph" concept,
alpar@1010
   321
  ///it also provides several additional useful extra functionalities.
klao@959
   322
  ///\sa concept::ErasableGraph.
deba@782
   323
deba@1999
   324
  class ListGraph : public ExtendedListGraphBase {
alpar@948
   325
  public:
deba@1999
   326
deba@1999
   327
    typedef ExtendedListGraphBase Parent;
deba@1999
   328
alpar@1546
   329
    /// Changes the target of \c e to \c n
alpar@948
   330
alpar@1546
   331
    /// Changes the target of \c e to \c n
alpar@948
   332
    ///
alpar@1010
   333
    ///\note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
alpar@1546
   334
    ///referencing the changed edge remain
alpar@1010
   335
    ///valid. However <tt>InEdge</tt>'s are invalidated.
deba@1718
   336
    void changeTarget(Edge e, Node n) { 
deba@1718
   337
      _changeTarget(e,n); 
deba@1718
   338
    }
alpar@1546
   339
    /// Changes the source of \c e to \c n
alpar@948
   340
alpar@1546
   341
    /// Changes the source of \c e to \c n
alpar@948
   342
    ///
alpar@1010
   343
    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
alpar@1546
   344
    ///referencing the changed edge remain
alpar@1010
   345
    ///valid. However <tt>OutEdge</tt>'s are invalidated.
deba@1718
   346
    void changeSource(Edge e, Node n) { 
deba@1718
   347
      _changeSource(e,n);
deba@1718
   348
    }
alpar@949
   349
alpar@1010
   350
    /// Invert the direction of an edge.
alpar@1010
   351
alpar@1010
   352
    ///\note The <tt>Edge</tt>'s
alpar@1546
   353
    ///referencing the changed edge remain
alpar@1010
   354
    ///valid. However <tt>OutEdge</tt>'s  and <tt>InEdge</tt>'s are invalidated.
alpar@1010
   355
    void reverseEdge(Edge e) {
alpar@1010
   356
      Node t=target(e);
alpar@1546
   357
      _changeTarget(e,source(e));
alpar@1546
   358
      _changeSource(e,t);
alpar@1010
   359
    }
alpar@1010
   360
alpar@1010
   361
    ///Using this it possible to avoid the superfluous memory allocation.
alpar@1010
   362
alpar@949
   363
    ///Using this it possible to avoid the superfluous memory allocation.
alpar@949
   364
    ///\todo more docs...
alpar@949
   365
    void reserveEdge(int n) { edges.reserve(n); };
alpar@1010
   366
alpar@1010
   367
    ///Contract two nodes.
alpar@1010
   368
alpar@1010
   369
    ///This function contracts two nodes.
alpar@1010
   370
    ///
alpar@1010
   371
    ///Node \p b will be removed but instead of deleting
alpar@1010
   372
    ///its neighboring edges, they will be joined to \p a.
alpar@1010
   373
    ///The last parameter \p r controls whether to remove loops. \c true
alpar@1010
   374
    ///means that loops will be removed.
alpar@1010
   375
    ///
alpar@1010
   376
    ///\note The <tt>Edge</tt>s
alpar@1281
   377
    ///referencing a moved edge remain
alpar@1010
   378
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1010
   379
    ///may be invalidated.
deba@1718
   380
    void contract(Node a, Node b, bool r = true) 
alpar@1010
   381
    {
alpar@1010
   382
      for(OutEdgeIt e(*this,b);e!=INVALID;) {
alpar@1010
   383
	OutEdgeIt f=e;
alpar@1010
   384
	++f;
alpar@1010
   385
	if(r && target(e)==a) erase(e);
alpar@1546
   386
	else changeSource(e,a);
alpar@1010
   387
	e=f;
alpar@1010
   388
      }
alpar@1010
   389
      for(InEdgeIt e(*this,b);e!=INVALID;) {
alpar@1010
   390
	InEdgeIt f=e;
alpar@1010
   391
	++f;
alpar@1010
   392
	if(r && source(e)==a) erase(e);
alpar@1546
   393
	else changeTarget(e,a);
alpar@1010
   394
	e=f;
alpar@1010
   395
      }
alpar@1010
   396
      erase(b);
alpar@1010
   397
    }
alpar@1011
   398
alpar@1281
   399
    ///Split a node.
alpar@1011
   400
alpar@1284
   401
    ///This function splits a node. First a new node is added to the graph,
alpar@1284
   402
    ///then the source of each outgoing edge of \c n is moved to this new node.
alpar@1281
   403
    ///If \c connect is \c true (this is the default value), then a new edge
alpar@1281
   404
    ///from \c n to the newly created node is also added.
alpar@1281
   405
    ///\return The newly created node.
alpar@1281
   406
    ///
alpar@1281
   407
    ///\note The <tt>Edge</tt>s
alpar@1281
   408
    ///referencing a moved edge remain
alpar@1281
   409
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1281
   410
    ///may be invalidated.
alpar@1770
   411
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1284
   412
    ///feature.
alpar@1281
   413
    ///\todo It could be implemented in a bit faster way.
alpar@1281
   414
    Node split(Node n, bool connect = true) 
alpar@1281
   415
    {
alpar@1281
   416
      Node b = addNode();
alpar@1281
   417
      for(OutEdgeIt e(*this,n);e!=INVALID;) {
alpar@1281
   418
 	OutEdgeIt f=e;
alpar@1281
   419
	++f;
alpar@1546
   420
	changeSource(e,b);
alpar@1281
   421
	e=f;
alpar@1281
   422
      }
alpar@1281
   423
      if(connect) addEdge(n,b);
alpar@1281
   424
      return b;
alpar@1281
   425
    }
alpar@1281
   426
      
alpar@1812
   427
    ///Split an edge.
alpar@1812
   428
alpar@1812
   429
    ///This function splits an edge. First a new node \c b is added to the graph,
alpar@1812
   430
    ///then the original edge is re-targetes to \c b. Finally an edge
alpar@1812
   431
    ///from \c b to the original target is added.
alpar@1812
   432
    ///\return The newly created node.
alpar@1812
   433
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1812
   434
    ///feature.
alpar@1812
   435
    Node split(Edge e) 
alpar@1812
   436
    {
alpar@1812
   437
      Node b = addNode();
alpar@1812
   438
      addEdge(b,target(e));
alpar@1812
   439
      changeTarget(e,b);
alpar@1812
   440
      return b;
alpar@1812
   441
    }
alpar@1812
   442
      
alpar@1011
   443
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   444
alpar@1011
   445
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   446
    ///
alpar@1011
   447
    ///The newly added nodes and edges can be removed using the
alpar@1011
   448
    ///restore() function.
alpar@1011
   449
    ///
alpar@1011
   450
    ///\warning Edge and node deletions cannot be restored.
alpar@1770
   451
    ///\warning Snapshots cannot be nested.
deba@1999
   452
    class Snapshot : protected Parent::NodeNotifier::ObserverBase,
deba@1999
   453
		     protected Parent::EdgeNotifier::ObserverBase
alpar@1011
   454
    {
deba@1774
   455
    public:
deba@1774
   456
      
deba@1774
   457
      class UnsupportedOperation : public LogicError {
deba@1774
   458
      public:
deba@1774
   459
	virtual const char* exceptionName() const {
deba@1774
   460
	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
deba@1774
   461
	}
deba@1774
   462
      };
deba@1774
   463
            
deba@1774
   464
deba@1999
   465
    protected:
alpar@1011
   466
      
alpar@1011
   467
      ListGraph *g;
alpar@1011
   468
      std::list<Node> added_nodes;
alpar@1011
   469
      std::list<Edge> added_edges;
alpar@1011
   470
      
alpar@1011
   471
      bool active;
alpar@1011
   472
      virtual void add(const Node& n) {
alpar@1011
   473
	added_nodes.push_back(n);
alpar@1011
   474
      };
alpar@1011
   475
      virtual void erase(const Node&) 
alpar@1011
   476
      {
deba@1774
   477
	throw UnsupportedOperation();
alpar@1011
   478
      }
alpar@1011
   479
      virtual void add(const Edge& n) {
alpar@1011
   480
	added_edges.push_back(n);
alpar@1011
   481
      };
alpar@1011
   482
      virtual void erase(const Edge&) 
alpar@1011
   483
      {
deba@1774
   484
	throw UnsupportedOperation();
alpar@1011
   485
      }
alpar@1011
   486
alpar@1457
   487
      ///\bug What is this used for?
alpar@1457
   488
      ///
alpar@1457
   489
      virtual void build() {}
alpar@1457
   490
      ///\bug What is this used for?
alpar@1457
   491
      ///
alpar@1457
   492
      virtual void clear() {}
alpar@1457
   493
alpar@1011
   494
      void regist(ListGraph &_g) {
alpar@1011
   495
	g=&_g;
deba@1999
   496
	Parent::NodeNotifier::ObserverBase::attach(g->getNotifier(Node()));
deba@1999
   497
	Parent::EdgeNotifier::ObserverBase::attach(g->getNotifier(Edge()));
alpar@1011
   498
      }
alpar@1011
   499
            
alpar@1011
   500
      void deregist() {
deba@1999
   501
	Parent::NodeNotifier::ObserverBase::detach();
deba@1999
   502
	Parent::EdgeNotifier::ObserverBase::detach();
alpar@1011
   503
	g=0;
alpar@1011
   504
      }
deba@1774
   505
alpar@1011
   506
    public:
alpar@1011
   507
      ///Default constructur.
alpar@1011
   508
      
alpar@1011
   509
      ///Default constructur.
alpar@1011
   510
      ///To actually make a snapshot you must call save().
alpar@1011
   511
      ///
alpar@1770
   512
      Snapshot() : g(0) {}
alpar@1011
   513
      ///Constructor that immediately makes a snapshot.
alpar@1011
   514
      
alpar@1011
   515
      ///This constructor immediately makes a snapshot of the graph.
alpar@1011
   516
      ///\param _g The graph we make a snapshot of.
alpar@1770
   517
      Snapshot(ListGraph &_g) {
alpar@1011
   518
	regist(_g);
alpar@1011
   519
      }
alpar@1011
   520
      ///\bug Is it necessary?
alpar@1011
   521
      ///
alpar@1770
   522
      ~Snapshot() 
alpar@1011
   523
      {
alpar@1011
   524
	if(g) deregist();
alpar@1011
   525
      }
alpar@1011
   526
      
alpar@1011
   527
      ///Make a snapshot.
alpar@1011
   528
alpar@1011
   529
      ///Make a snapshot of the graph.
alpar@1011
   530
      ///
alpar@1011
   531
      ///This function can be called more than once. In case of a repeated
alpar@1011
   532
      ///call, the previous snapshot gets lost.
alpar@1011
   533
      ///\param _g The graph we make the snapshot of.
alpar@1011
   534
      void save(ListGraph &_g) 
alpar@1011
   535
      {
alpar@1011
   536
	if(g!=&_g) {
alpar@1011
   537
	  if(g) deregist();
alpar@1011
   538
	  regist(_g);
alpar@1011
   539
	}
alpar@1011
   540
	added_nodes.clear();
alpar@1011
   541
	added_edges.clear();
alpar@1011
   542
      }
alpar@1011
   543
      
alpar@1011
   544
    ///Undo the changes until the last snapshot.
alpar@1011
   545
alpar@1011
   546
    ///Undo the changes until last snapshot created by save().
alpar@1011
   547
    ///
alpar@1011
   548
    ///\todo This function might be called undo().
alpar@1011
   549
      void restore() {
alpar@1457
   550
	ListGraph &old_g=*g;
alpar@1011
   551
	deregist();
alpar@1011
   552
	while(!added_edges.empty()) {
alpar@1457
   553
	  old_g.erase(added_edges.front());
alpar@1011
   554
	  added_edges.pop_front();
alpar@1011
   555
	}
alpar@1011
   556
 	while(!added_nodes.empty()) {
alpar@1457
   557
	  old_g.erase(added_nodes.front());
alpar@1011
   558
	  added_nodes.pop_front();
alpar@1011
   559
	}
alpar@1011
   560
      }
alpar@1011
   561
    };
alpar@1011
   562
    
alpar@949
   563
  };
klao@1034
   564
alpar@1555
   565
  ///@}
klao@1034
   566
klao@1034
   567
  /**************** Undirected List Graph ****************/
klao@1034
   568
deba@1979
   569
  typedef UGraphExtender<UGraphBaseExtender<
deba@1979
   570
    ListGraphBase> > ExtendedListUGraphBase;
klao@1034
   571
deba@1718
   572
  /// \addtogroup graphs
deba@1718
   573
  /// @{
alpar@1555
   574
alpar@1035
   575
  ///An undirected list graph class.
alpar@1035
   576
alpar@1035
   577
  ///This is a simple and fast erasable undirected graph implementation.
alpar@1035
   578
  ///
alpar@1035
   579
  ///It conforms to the
klao@1909
   580
  ///\ref concept::UGraph "UGraph" concept.
alpar@1035
   581
  ///
klao@1909
   582
  ///\sa concept::UGraph.
alpar@1035
   583
  ///
alpar@1770
   584
  ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
alpar@1161
   585
  ///haven't been implemented yet.
alpar@1035
   586
  ///
klao@1909
   587
  class ListUGraph : public ExtendedListUGraphBase {
deba@1718
   588
  public:
klao@1909
   589
    typedef ExtendedListUGraphBase Parent;
deba@1718
   590
    /// \brief Changes the target of \c e to \c n
deba@1718
   591
    ///
deba@1718
   592
    /// Changes the target of \c e to \c n
deba@1718
   593
    ///
deba@1718
   594
    /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
deba@1718
   595
    /// referencing the changed edge remain
deba@1718
   596
    /// valid. However <tt>InEdge</tt>'s are invalidated.
klao@1909
   597
    void changeTarget(UEdge e, Node n) { 
deba@1718
   598
      _changeTarget(e,n); 
deba@1718
   599
    }
deba@1718
   600
    /// Changes the source of \c e to \c n
deba@1718
   601
    ///
deba@1718
   602
    /// Changes the source of \c e to \c n
deba@1718
   603
    ///
deba@1718
   604
    ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
deba@1718
   605
    ///referencing the changed edge remain
deba@1718
   606
    ///valid. However <tt>OutEdge</tt>'s are invalidated.
klao@1909
   607
    void changeSource(UEdge e, Node n) { 
deba@1718
   608
      _changeSource(e,n); 
deba@1718
   609
    }
deba@1718
   610
    /// \brief Contract two nodes.
deba@1718
   611
    ///
deba@1718
   612
    /// This function contracts two nodes.
deba@1718
   613
    ///
deba@1718
   614
    /// Node \p b will be removed but instead of deleting
deba@1718
   615
    /// its neighboring edges, they will be joined to \p a.
deba@1718
   616
    /// The last parameter \p r controls whether to remove loops. \c true
deba@1718
   617
    /// means that loops will be removed.
deba@1718
   618
    ///
deba@1718
   619
    /// \note The <tt>Edge</tt>s
deba@1718
   620
    /// referencing a moved edge remain
deba@1718
   621
    /// valid.
deba@1718
   622
    void contract(Node a, Node b, bool r = true) {
deba@1718
   623
      for(IncEdgeIt e(*this, b); e!=INVALID;) {
deba@1718
   624
	IncEdgeIt f = e; ++f;
deba@1718
   625
	if (r && runningNode(e) == a) {
deba@1718
   626
	  erase(e);
deba@1718
   627
	} else if (source(e) == b) {
deba@1718
   628
	  changeSource(e, a);
deba@1718
   629
	} else {
deba@1718
   630
	  changeTarget(e, a);
deba@1718
   631
	}
deba@1718
   632
	e = f;
deba@1718
   633
      }
deba@1718
   634
      erase(b);
deba@1718
   635
    }
klao@1034
   636
  };
klao@1034
   637
deba@1982
   638
deba@1982
   639
  class ListBpUGraphBase {
deba@1982
   640
  public:
deba@1982
   641
deba@1982
   642
    class NodeSetError : public LogicError {
deba@1982
   643
      virtual const char* exceptionName() const { 
deba@1982
   644
	return "lemon::ListBpUGraph::NodeSetError";
deba@1982
   645
      }
deba@1982
   646
    };
deba@1982
   647
deba@1982
   648
  protected:
deba@1982
   649
deba@1982
   650
    struct NodeT {
deba@1982
   651
      int first_edge, next_node;
deba@1982
   652
    };
deba@1982
   653
deba@1982
   654
    struct EdgeT {
deba@1982
   655
      int aNode, prev_out, next_out;
deba@1982
   656
      int bNode, prev_in, next_in;
deba@1982
   657
    };
deba@1982
   658
deba@1982
   659
    std::vector<NodeT> aNodes;
deba@1982
   660
    std::vector<NodeT> bNodes;
deba@1982
   661
deba@1982
   662
    std::vector<EdgeT> edges;
deba@1982
   663
deba@1982
   664
    int first_anode;
deba@1982
   665
    int first_free_anode;
deba@1982
   666
deba@1982
   667
    int first_bnode;
deba@1982
   668
    int first_free_bnode;
deba@1982
   669
deba@1982
   670
    int first_free_edge;
deba@1982
   671
deba@1982
   672
  public:
deba@1982
   673
  
deba@1982
   674
    class Node {
deba@1982
   675
      friend class ListBpUGraphBase;
deba@1982
   676
    protected:
deba@1982
   677
      int id;
deba@1982
   678
deba@2031
   679
      explicit Node(int _id) : id(_id) {}
deba@1982
   680
    public:
deba@1982
   681
      Node() {}
deba@1982
   682
      Node(Invalid) { id = -1; }
deba@1982
   683
      bool operator==(const Node i) const {return id==i.id;}
deba@1982
   684
      bool operator!=(const Node i) const {return id!=i.id;}
deba@1982
   685
      bool operator<(const Node i) const {return id<i.id;}
deba@1982
   686
    };
deba@1982
   687
deba@1982
   688
    class Edge {
deba@1982
   689
      friend class ListBpUGraphBase;
deba@1982
   690
    protected:
deba@1982
   691
      int id;
deba@1982
   692
deba@2031
   693
      explicit Edge(int _id) { id = _id;}
deba@1982
   694
    public:
deba@1982
   695
      Edge() {}
deba@1982
   696
      Edge (Invalid) { id = -1; }
deba@1982
   697
      bool operator==(const Edge i) const {return id==i.id;}
deba@1982
   698
      bool operator!=(const Edge i) const {return id!=i.id;}
deba@1982
   699
      bool operator<(const Edge i) const {return id<i.id;}
deba@1982
   700
    };
deba@1982
   701
deba@1982
   702
    ListBpUGraphBase()
deba@1982
   703
      : first_anode(-1), first_free_anode(-1),
deba@1982
   704
        first_bnode(-1), first_free_bnode(-1),
deba@1982
   705
        first_free_edge(-1) {}
deba@1982
   706
deba@1982
   707
    void firstANode(Node& node) const {
deba@1982
   708
      node.id = first_anode != -1 ? (first_anode << 1) : -1;
deba@1982
   709
    }
deba@1982
   710
    void nextANode(Node& node) const {
deba@1982
   711
      node.id = aNodes[node.id >> 1].next_node;
deba@1982
   712
    }
deba@1982
   713
deba@1982
   714
    void firstBNode(Node& node) const {
deba@1982
   715
      node.id =  first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
deba@1982
   716
    }
deba@1982
   717
    void nextBNode(Node& node) const {
deba@1984
   718
      node.id = bNodes[node.id >> 1].next_node;
deba@1982
   719
    }
deba@1982
   720
deba@1982
   721
    void first(Node& node) const {
deba@1982
   722
      if (first_anode != -1) {
deba@1982
   723
        node.id = (first_anode << 1);
deba@1982
   724
      } else if (first_bnode != -1) {
deba@1982
   725
        node.id = (first_bnode << 1) + 1;
deba@1982
   726
      } else {
deba@1982
   727
        node.id = -1;
deba@1982
   728
      }
deba@1982
   729
    }
deba@1982
   730
    void next(Node& node) const {
deba@1982
   731
      if (aNode(node)) {
deba@1982
   732
        node.id = aNodes[node.id >> 1].next_node;
deba@1982
   733
        if (node.id == -1) {
deba@1982
   734
          if (first_bnode != -1) {
deba@1982
   735
            node.id = (first_bnode << 1) + 1;
deba@1982
   736
          }
deba@1982
   737
        }
deba@1982
   738
      } else {
deba@1982
   739
        node.id = bNodes[node.id >> 1].next_node;
deba@1982
   740
      }
deba@1982
   741
    }
deba@1982
   742
  
deba@1982
   743
    void first(Edge& edge) const {
deba@1982
   744
      int aNodeId = first_anode;
deba@1982
   745
      while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
deba@1982
   746
        aNodeId = aNodes[aNodeId].next_node != -1 ? 
deba@1982
   747
          aNodes[aNodeId].next_node >> 1 : -1;
deba@1982
   748
      }
deba@1982
   749
      if (aNodeId != -1) {
deba@1982
   750
        edge.id = aNodes[aNodeId].first_edge;
deba@1982
   751
      } else {
deba@1982
   752
        edge.id = -1;
deba@1982
   753
      }
deba@1982
   754
    }
deba@1982
   755
    void next(Edge& edge) const {
deba@1982
   756
      int aNodeId = edges[edge.id].aNode >> 1;
deba@1982
   757
      edge.id = edges[edge.id].next_out;
deba@1982
   758
      if (edge.id == -1) {
deba@1982
   759
        aNodeId = aNodes[aNodeId].next_node != -1 ? 
deba@1982
   760
          aNodes[aNodeId].next_node >> 1 : -1;
deba@1982
   761
        while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
deba@1982
   762
          aNodeId = aNodes[aNodeId].next_node != -1 ? 
deba@1982
   763
          aNodes[aNodeId].next_node >> 1 : -1;
deba@1982
   764
        }
deba@1982
   765
        if (aNodeId != -1) {
deba@1982
   766
          edge.id = aNodes[aNodeId].first_edge;
deba@1982
   767
        } else {
deba@1982
   768
          edge.id = -1;
deba@1982
   769
        }
deba@1982
   770
      }
deba@1982
   771
    }
deba@1982
   772
deba@1982
   773
    void firstOut(Edge& edge, const Node& node) const {
deba@1982
   774
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@1982
   775
      edge.id = aNodes[node.id >> 1].first_edge;
deba@1982
   776
    }
deba@1982
   777
    void nextOut(Edge& edge) const {
deba@1982
   778
      edge.id = edges[edge.id].next_out;
deba@1982
   779
    }
deba@1982
   780
deba@1982
   781
    void firstIn(Edge& edge, const Node& node) const {
deba@1982
   782
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@1982
   783
      edge.id = bNodes[node.id >> 1].first_edge;
deba@1982
   784
    }
deba@1982
   785
    void nextIn(Edge& edge) const {
deba@1982
   786
      edge.id = edges[edge.id].next_in;
deba@1982
   787
    }
deba@1982
   788
deba@1982
   789
    static int id(const Node& node) {
deba@1982
   790
      return node.id;
deba@1982
   791
    }
deba@1982
   792
    static Node nodeFromId(int id) {
deba@1982
   793
      return Node(id);
deba@1982
   794
    }
deba@1982
   795
    int maxNodeId() const {
deba@1982
   796
      return aNodes.size() > bNodes.size() ?
deba@1982
   797
	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
deba@1982
   798
    }
deba@1982
   799
  
deba@1982
   800
    static int id(const Edge& edge) {
deba@1982
   801
      return edge.id;
deba@1982
   802
    }
deba@1982
   803
    static Edge edgeFromId(int id) {
deba@1982
   804
      return Edge(id);
deba@1982
   805
    }
deba@1982
   806
    int maxEdgeId() const {
deba@1982
   807
      return edges.size();
deba@1982
   808
    }
deba@1982
   809
  
deba@1982
   810
    static int aNodeId(const Node& node) {
deba@1982
   811
      return node.id >> 1;
deba@1982
   812
    }
deba@1995
   813
    static Node fromANodeId(int id) {
deba@1982
   814
      return Node(id << 1);
deba@1982
   815
    }
deba@1982
   816
    int maxANodeId() const {
deba@1982
   817
      return aNodes.size();
deba@1982
   818
    }
deba@1982
   819
deba@1982
   820
    static int bNodeId(const Node& node) {
deba@1982
   821
      return node.id >> 1;
deba@1982
   822
    }
deba@1982
   823
    static Node fromBNodeId(int id) {
deba@1982
   824
      return Node((id << 1) + 1);
deba@1982
   825
    }
deba@1982
   826
    int maxBNodeId() const {
deba@1982
   827
      return bNodes.size();
deba@1982
   828
    }
deba@1982
   829
deba@1982
   830
    Node aNode(const Edge& edge) const {
deba@1982
   831
      return Node(edges[edge.id].aNode);
deba@1982
   832
    }
deba@1982
   833
    Node bNode(const Edge& edge) const {
deba@1982
   834
      return Node(edges[edge.id].bNode);
deba@1982
   835
    }
deba@1982
   836
deba@1982
   837
    static bool aNode(const Node& node) {
deba@1982
   838
      return (node.id & 1) == 0;
deba@1982
   839
    }
deba@1982
   840
deba@1982
   841
    static bool bNode(const Node& node) {
deba@1982
   842
      return (node.id & 1) == 1;
deba@1982
   843
    }
deba@1982
   844
deba@1982
   845
    Node addANode() {
deba@1982
   846
      int aNodeId;
deba@1982
   847
      if (first_free_anode == -1) {
deba@1982
   848
        aNodeId = aNodes.size();
deba@1982
   849
        aNodes.push_back(NodeT());
deba@1982
   850
      } else {
deba@1982
   851
        aNodeId = first_free_anode;
deba@1982
   852
        first_free_anode = aNodes[first_free_anode].next_node;
deba@1982
   853
      }
deba@1982
   854
      aNodes[aNodeId].next_node = 
deba@1982
   855
        first_anode != -1 ? (first_anode << 1) : -1;
deba@1982
   856
      first_anode = aNodeId;
deba@1982
   857
      aNodes[aNodeId].first_edge = -1;
deba@1982
   858
      return Node(aNodeId << 1);
deba@1982
   859
    }
deba@1982
   860
deba@1982
   861
    Node addBNode() {
deba@1982
   862
      int bNodeId;
deba@1984
   863
      if (first_free_bnode == -1) {
deba@1982
   864
        bNodeId = bNodes.size();
deba@1982
   865
        bNodes.push_back(NodeT());
deba@1982
   866
      } else {
deba@1982
   867
        bNodeId = first_free_bnode;
deba@1982
   868
        first_free_bnode = bNodes[first_free_bnode].next_node;
deba@1982
   869
      }
deba@1982
   870
      bNodes[bNodeId].next_node = 
deba@1982
   871
        first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
deba@1982
   872
      first_bnode = bNodeId;
deba@1982
   873
      bNodes[bNodeId].first_edge = -1;
deba@1982
   874
      return Node((bNodeId << 1) + 1);
deba@1982
   875
    }
deba@1982
   876
deba@1982
   877
    Edge addEdge(const Node& source, const Node& target) {
deba@1982
   878
      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
deba@1982
   879
      int edgeId;
deba@1982
   880
      if (first_free_edge != -1) {
deba@1982
   881
        edgeId = first_free_edge;
deba@1982
   882
        first_free_edge = edges[edgeId].next_out;
deba@1982
   883
      } else {
deba@1982
   884
        edgeId = edges.size();
deba@1982
   885
        edges.push_back(EdgeT());
deba@1982
   886
      }
deba@1982
   887
      if ((source.id & 1) == 0) {
deba@1982
   888
	edges[edgeId].aNode = source.id;
deba@1982
   889
	edges[edgeId].bNode = target.id;
deba@1982
   890
      } else {
deba@1982
   891
	edges[edgeId].aNode = target.id;
deba@1982
   892
	edges[edgeId].bNode = source.id;
deba@1982
   893
      }
deba@1982
   894
      edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
deba@1982
   895
      edges[edgeId].prev_out = -1;
deba@1982
   896
      if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
deba@1982
   897
        edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
deba@1982
   898
      }
deba@1982
   899
      aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
deba@1982
   900
      edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
deba@1982
   901
      edges[edgeId].prev_in = -1;
deba@1982
   902
      if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
deba@1982
   903
        edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
deba@1982
   904
      }
deba@1982
   905
      bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
deba@1982
   906
      return Edge(edgeId);
deba@1982
   907
    }
deba@1982
   908
deba@1982
   909
    void erase(const Node& node) {
deba@1982
   910
      if (aNode(node)) {
deba@1982
   911
        int aNodeId = node.id >> 1;
deba@1982
   912
        aNodes[aNodeId].next_node = first_free_anode;
deba@1982
   913
        first_free_anode = aNodeId;
deba@1982
   914
      } else {
deba@1982
   915
        int bNodeId = node.id >> 1;
deba@1982
   916
        bNodes[bNodeId].next_node = first_free_bnode;
deba@1982
   917
        first_free_bnode = bNodeId;
deba@1982
   918
      }
deba@1982
   919
    }
deba@1982
   920
deba@1982
   921
    void erase(const Edge& edge) {
deba@1982
   922
      if (edges[edge.id].prev_out != -1) {
deba@1982
   923
        edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
deba@1982
   924
      } else {
deba@1982
   925
        aNodes[edges[edge.id].aNode].first_edge = edges[edge.id].next_out;
deba@1982
   926
      }
deba@1982
   927
      if (edges[edge.id].next_out != -1) {
deba@1982
   928
        edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
deba@1982
   929
      }
deba@1982
   930
      if (edges[edge.id].prev_in != -1) {
deba@1982
   931
        edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
deba@1982
   932
      } else {
deba@1982
   933
        bNodes[edges[edge.id].bNode].first_edge = edges[edge.id].next_in;
deba@1982
   934
      }
deba@1982
   935
      if (edges[edge.id].next_in != -1) {
deba@1982
   936
        edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
deba@1982
   937
      }
deba@1982
   938
      edges[edge.id].next_out = first_free_edge;
deba@1982
   939
      first_free_edge = edge.id;
deba@1982
   940
    }
deba@1982
   941
deba@1982
   942
    void clear() {
deba@1982
   943
      aNodes.clear();
deba@1982
   944
      bNodes.clear();
deba@1982
   945
      edges.clear();
deba@1982
   946
      first_anode = -1;
deba@1982
   947
      first_free_anode = -1;
deba@1982
   948
      first_bnode = -1;
deba@1982
   949
      first_free_bnode = -1;
deba@1982
   950
      first_free_edge = -1;
deba@1982
   951
    }
deba@1982
   952
deba@1982
   953
  };
deba@1982
   954
deba@1982
   955
deba@1982
   956
  typedef BpUGraphExtender< BpUGraphBaseExtender<
deba@1982
   957
    ListBpUGraphBase> > ExtendedListBpUGraphBase;
deba@1982
   958
deba@1982
   959
  /// \ingroup graphs
deba@1982
   960
  ///
deba@1982
   961
  /// \brief A smart bipartite undirected graph class.
deba@1982
   962
  ///
deba@1982
   963
  /// This is a bipartite undirected graph implementation.
deba@1991
   964
  /// It is conforms to the \ref concept::ErasableBpUGraph "ErasableBpUGraph" 
deba@1991
   965
  /// concept.
deba@1982
   966
  /// \sa concept::BpUGraph.
deba@1982
   967
  ///
deba@1982
   968
  class ListBpUGraph : public ExtendedListBpUGraphBase {};
deba@1982
   969
alpar@949
   970
  
alpar@948
   971
  /// @}  
alpar@948
   972
} //namespace lemon
klao@946
   973
  
alpar@400
   974
klao@946
   975
#endif